aboutsummaryrefslogtreecommitdiffstats
path: root/python
diff options
context:
space:
mode:
Diffstat (limited to 'python')
-rw-r--r--python/env.example2
-rw-r--r--python/fatcat_web/auth.py57
-rw-r--r--python/fatcat_web/routes.py11
-rw-r--r--python/fatcat_web/templates/auth_ia_login.html31
-rw-r--r--python/fatcat_web/templates/auth_login.html1
-rw-r--r--python/fatcat_web/templates/base.html2
-rw-r--r--python/fatcat_web/web_config.py8
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