diff options
| author | Bryan Newbold <bnewbold@robocracy.org> | 2019-01-07 17:43:34 -0800 | 
|---|---|---|
| committer | Bryan Newbold <bnewbold@robocracy.org> | 2019-01-07 17:43:34 -0800 | 
| commit | 5d5a5648cb480e05c4253c954c71094c7251b65a (patch) | |
| tree | 37a42db8e57d190c95c448b77e9eac580fe8417a /python | |
| parent | a373cda815b0a44d93b485800b63a785c9aeb8aa (diff) | |
| download | fatcat-5d5a5648cb480e05c4253c954c71094c7251b65a.tar.gz fatcat-5d5a5648cb480e05c4253c954c71094c7251b65a.zip | |
basic/crude IA login
Diffstat (limited to 'python')
| -rw-r--r-- | python/env.example | 2 | ||||
| -rw-r--r-- | python/fatcat_web/auth.py | 57 | ||||
| -rw-r--r-- | python/fatcat_web/routes.py | 11 | ||||
| -rw-r--r-- | python/fatcat_web/templates/auth_ia_login.html | 31 | ||||
| -rw-r--r-- | python/fatcat_web/templates/auth_login.html | 1 | ||||
| -rw-r--r-- | python/fatcat_web/templates/base.html | 2 | ||||
| -rw-r--r-- | python/fatcat_web/web_config.py | 8 | 
7 files changed, 103 insertions, 9 deletions
| diff --git a/python/env.example b/python/env.example index c139df07..c13c6246 100644 --- a/python/env.example +++ b/python/env.example @@ -5,4 +5,6 @@ ELASTICSEARCH_BACKEND="http://localhost:9200"  ELASTICSEARCH_INDEX="fatcat"  GITLAB_CLIENT_ID=""  GITLAB_CLIENT_SECRET="" +IA_XAUTH_CLIENT_ID="" +IA_XAUTH_CLIENT_SECRET=""  SENTRY_DSN="" diff --git a/python/fatcat_web/auth.py b/python/fatcat_web/auth.py index 8b57a8c0..8035cbe5 100644 --- a/python/fatcat_web/auth.py +++ b/python/fatcat_web/auth.py @@ -1,16 +1,19 @@ +from collections import namedtuple +import requests +import pymacaroons  from flask import Flask, render_template, send_from_directory, request, \      url_for, abort, g, redirect, jsonify, session, flash  from fatcat_web import login_manager, api, priv_api, Config  from flask_login import logout_user, login_user, UserMixin -import pymacaroons  import fatcat_client  def handle_logout():      logout_user() -    for k in ('editor', 'token'): +    for k in ('editor', 'api_token'):          if k in session:              session.pop(k) +    session.clear()  def handle_token_login(token):      try: @@ -73,14 +76,59 @@ def handle_oauth(remote, token, user_info):          login_user(load_user(editor.editor_id))          return redirect("/auth/account") -    raise some_error +    # XXX: what should this actually be? +    raise Exception("didn't receive OAuth user_info") + +def handle_ia_xauth(email, password): +    resp = requests.post(Config.IA_XAUTH_URI, +        params={'op': 'authenticate'}, +        json={ +            'version': '1', +            'email': email, +            'password': password, +            'access': Config.IA_XAUTH_CLIENT_ID, +            'secret': Config.IA_XAUTH_CLIENT_SECRET, +        }) +    if resp.status_code == 401 or (not resp.json().get('success')): +        flash("Internet Archive email/password didn't match: {}".format(resp.json()['values']['reason'])) +        return render_template('auth_ia_login.html', email=email), resp.status_code +    elif resp.status_code != 200: +        flash("Internet Archive login failed (internal error?)") +        # TODO: log.warn +        print("IA XAuth fail: {}".format(resp.content)) +        return render_template('auth_ia_login.html', email=email), resp.status_code +    # Successful login; now fetch info... +    resp = requests.post(Config.IA_XAUTH_URI, +        params={'op': 'info'}, +        json={ +            'version': '1', +            'email': email, +            'access': Config.IA_XAUTH_CLIENT_ID, +            'secret': Config.IA_XAUTH_CLIENT_SECRET, +        }) +    if resp.status_code != 200: +        flash("Internet Archive login failed (internal error?)") +        # TODO: log.warn +        print("IA XAuth fail: {}".format(resp.content)) +        return render_template('auth_ia_login.html', email=email), resp.status_code +    ia_info = resp.json()['values'] + +    # and pass off "as if" we did OAuth successfully +    FakeOAuthRemote = namedtuple('FakeOAuthRemote', ['name', 'OAUTH_CONFIG']) +    remote = FakeOAuthRemote(name='archive', OAUTH_CONFIG={'api_base_url': Config.IA_XAUTH_URI}) +    oauth_info = { +        'preferred_username': ia_info['screenname'], +        'iss': Config.IA_XAUTH_URI, +        'sub': ia_info['itemname'], +    } +    return handle_oauth(remote, None, oauth_info)  @login_manager.user_loader  def load_user(editor_id):      # looks for extra info in session, and updates the user object with that.      # If session isn't loaded/valid, should return None -    if not 'editor' in session or not 'api_token' in session: +    if (not session.get('editor')) or (not session.get('api_token')):          return None      editor = session['editor']      token = session['api_token'] @@ -90,3 +138,4 @@ def load_user(editor_id):      user.username = editor['username']      user.token = token      return user + diff --git a/python/fatcat_web/routes.py b/python/fatcat_web/routes.py index ebf7e88a..789d7bed 100644 --- a/python/fatcat_web/routes.py +++ b/python/fatcat_web/routes.py @@ -5,7 +5,7 @@ from flask import Flask, render_template, send_from_directory, request, \      url_for, abort, g, redirect, jsonify, session, flash  from flask_login import login_required  from fatcat_web import app, api, auth_api -from fatcat_web.auth import handle_token_login, handle_logout, load_user +from fatcat_web.auth import handle_token_login, handle_logout, load_user, handle_ia_xauth  from fatcat_client.rest import ApiException  from fatcat_web.search import do_search @@ -381,6 +381,14 @@ def login():      # show the user a list of login options      return render_template('auth_login.html') +@app.route('/auth/ia/login', methods=['GET', 'POST']) +def ia_xauth_login(): +    if 'email' in request.form: +        # if a login attempt... +        return handle_ia_xauth(request.form.get('email'), request.form.get('password')) +    # else show form +    return render_template('auth_ia_login.html') +  @app.route('/auth/token_login', methods=['GET', 'POST'])  def token_login():      # show the user a list of login options @@ -409,7 +417,6 @@ def change_username():  @app.route('/auth/logout')  def logout(): -    # TODO: clear extra session info      handle_logout()      return render_template('auth_logout.html') diff --git a/python/fatcat_web/templates/auth_ia_login.html b/python/fatcat_web/templates/auth_ia_login.html new file mode 100644 index 00000000..ebf08021 --- /dev/null +++ b/python/fatcat_web/templates/auth_ia_login.html @@ -0,0 +1,31 @@ +{% extends "base.html" %} +{% block body %} +<h1>Login with Internet Archive account</h1> + +<p>Warning: still experimental! + +<br> +<br> +<br> + +{% if current_user.is_authenticated %} +  <div class="ui negative message"> +    <div class="header">You are already logged in!</div> +    <p>You should logout first. Re-authenticating would be undefined behavior. +  </div> +{% else %} +  <form class="" role="login" action="/auth/ia/login" method="post"> +    <div class="ui form"> +        <div class="ui input huge fluid"> +          <input type="email" placeholder="user@domain.tdl..." name="email" {% if email %}value="{{ email }}"{% endif %} aria-label="email for login"> +        </div> +        <div class="ui action input huge fluid"> +          <input type="password" placeholder="password" name="password" aria-label="internet archive password"> +          <button class="ui button">Login</button> +        </div> +      </div> +    </div> +  </form> +{% endif %} + +{% endblock %} diff --git a/python/fatcat_web/templates/auth_login.html b/python/fatcat_web/templates/auth_login.html index 98b1c7c4..9ccae816 100644 --- a/python/fatcat_web/templates/auth_login.html +++ b/python/fatcat_web/templates/auth_login.html @@ -12,6 +12,7 @@  <p>Other options...  <ul>    <li><a href="/auth/token_login">Using auth token</a> (admin/operator) +  <li><a href="/auth/ia/login">With Internet Archive account</a> (experimental)  </ul>  {% endblock %} diff --git a/python/fatcat_web/templates/base.html b/python/fatcat_web/templates/base.html index e3824213..3b324cba 100644 --- a/python/fatcat_web/templates/base.html +++ b/python/fatcat_web/templates/base.html @@ -55,7 +55,7 @@    {% if messages %}      <div class="ui message">      {# Needs more javascript: <i class="close icon"></i> #} -    <div class="header">Now Hear This!</div> +    <div class="header">Now Hear This...</div>      <ul class="list">      {% for message in messages %}        <li>{{ message }} diff --git a/python/fatcat_web/web_config.py b/python/fatcat_web/web_config.py index 85134762..0ae43a3a 100644 --- a/python/fatcat_web/web_config.py +++ b/python/fatcat_web/web_config.py @@ -31,8 +31,12 @@ class Config(object):      FLASK_SECRET_KEY = os.environ.get("FLASK_SECRET_KEY", default=None)      SECRET_KEY = FLASK_SECRET_KEY -    GITLAB_CLIENT_ID = os.environ.get("GITLAB_CLIENT_ID", default="bogus") -    GITLAB_CLIENT_SECRET = os.environ.get("GITLAB_CLIENT_SECRET", default="bogus") +    GITLAB_CLIENT_ID = os.environ.get("GITLAB_CLIENT_ID", default=None) +    GITLAB_CLIENT_SECRET = os.environ.get("GITLAB_CLIENT_SECRET", default=None) + +    IA_XAUTH_URI = "https://archive.org/services/xauthn/" +    IA_XAUTH_CLIENT_ID = os.environ.get("IA_XAUTH_CLIENT_ID", default=None) +    IA_XAUTH_CLIENT_SECRET = os.environ.get("IA_XAUTH_CLIENT_SECRET", default=None)      # protect cookies (which include API tokens)      SESSION_COOKIE_HTTPONLY = True | 
