1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
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'):
if k in session:
session.pop(k)
def handle_token_login(token):
try:
m = pymacaroons.Macaroon.deserialize(token)
except pymacaroons.exceptions.MacaroonDeserializationException:
# TODO: what kind of Exceptions?
return abort(400)
# extract editor_id
editor_id = None
for caveat in m.first_party_caveats():
caveat = caveat.caveat_id
if caveat.startswith(b"editor_id = "):
editor_id = caveat[12:].decode('utf-8')
if not editor_id:
abort(400)
# fetch editor info
editor = api.get_editor(editor_id)
session.permanent = True
session['api_token'] = token
session['editor'] = editor.to_dict()
login_user(load_user(editor.editor_id))
return redirect("/auth/account")
# This will need to login/signup via fatcatd API, then set token in session
def handle_oauth(remote, token, user_info):
if user_info:
# fetch api login/signup using user_info
# ISS is basically the API url (though more formal in OIDC)
# SUB is the stable internal identifier for the user (not usually the username itself)
# TODO: should have the real sub here
# TODO: would be nicer to pass preferred_username for account creation
iss = remote.OAUTH_CONFIG['api_base_url']
# we reuse 'preferred_username' for account name auto-creation (but
# don't store it otherwise in the backend, at least currently). But i'm
# not sure all loginpass backends will set it
if user_info.get('preferred_username'):
preferred_username = user_info['preferred_username']
else:
preferred_username = user_info['sub']
params = fatcat_client.AuthOidc(remote.name, user_info['sub'], iss, user_info['preferred_username'])
# this call requires admin privs
(resp, http_status, http_headers) = priv_api.auth_oidc_with_http_info(params)
editor = resp.editor
api_token = resp.token
if http_status == 201:
flash("Welcome to Fatcat! An account has been created for you with a temporary username; you may wish to change it under account settings")
flash("You must use the same mechanism ({}) to login in the future".format(remote.name))
else:
flash("Welcome back!")
# write token and username to session
session.permanent = True
session['api_token'] = api_token
session['editor'] = editor.to_dict()
# call login_user(load_user(editor_id))
login_user(load_user(editor.editor_id))
return redirect("/auth/account")
raise some_error
@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:
return None
editor = session['editor']
token = session['api_token']
user = UserMixin()
user.id = editor_id
user.editor_id = editor_id
user.username = editor['username']
user.token = token
return user
|