From 5d5a5648cb480e05c4253c954c71094c7251b65a Mon Sep 17 00:00:00 2001 From: Bryan Newbold Date: Mon, 7 Jan 2019 17:43:34 -0800 Subject: basic/crude IA login --- python/env.example | 2 + python/fatcat_web/auth.py | 57 ++++++++++++++++++++++++-- python/fatcat_web/routes.py | 11 ++++- python/fatcat_web/templates/auth_ia_login.html | 31 ++++++++++++++ python/fatcat_web/templates/auth_login.html | 1 + python/fatcat_web/templates/base.html | 2 +- python/fatcat_web/web_config.py | 8 +++- 7 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 python/fatcat_web/templates/auth_ia_login.html 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 %} +

Login with Internet Archive account

+ +

Warning: still experimental! + +
+
+
+ +{% if current_user.is_authenticated %} +

+
You are already logged in!
+

You should logout first. Re-authenticating would be undefined behavior. +

+{% else %} +
+
+
+ +
+
+ + +
+
+ +
+{% 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 @@

Other options...

{% 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 %}
{# Needs more javascript: #} -
Now Hear This!
+
Now Hear This...