From 00c0859a7df360380a479eb9dbc79057c0245969 Mon Sep 17 00:00:00 2001 From: Bryan Newbold Date: Thu, 3 Jan 2019 22:10:41 -0800 Subject: basic OIDC auth working --- python/fatcat_web/__init__.py | 11 +++++-- python/fatcat_web/auth.py | 57 ++++++++++++++++++++--------------- python/fatcat_web/routes.py | 4 +-- python/fatcat_web/templates/base.html | 2 +- 4 files changed, 44 insertions(+), 30 deletions(-) diff --git a/python/fatcat_web/__init__.py b/python/fatcat_web/__init__.py index 0afee70e..34618076 100644 --- a/python/fatcat_web/__init__.py +++ b/python/fatcat_web/__init__.py @@ -26,14 +26,21 @@ conf = fatcat_client.Configuration() conf.host = Config.FATCAT_API_HOST api = fatcat_client.DefaultApi(fatcat_client.ApiClient(conf)) -from fatcat_web import routes, auth +def auth_api(token): + conf = fatcat_client.Configuration() + conf.api_key["Authorization"] = token + conf.api_key_prefix["Authorization"] = "Bearer" + conf.host = Config.FATCAT_API_HOST + return fatcat_client.DefaultApi(fatcat_client.ApiClient(conf)) if Config.FATCAT_API_AUTH_TOKEN: print("Found and using privileged token (eg, for account signup)") - priv_api = auth.auth_api(Config.FATCAT_API_AUTH_TOKEN) + priv_api = auth_api(Config.FATCAT_API_AUTH_TOKEN) else: print("No privileged token found") priv_api = None +from fatcat_web import routes, auth + gitlab_bp = create_flask_blueprint(Gitlab, oauth, auth.handle_oauth) app.register_blueprint(gitlab_bp, url_prefix='/auth/gitlab') diff --git a/python/fatcat_web/auth.py b/python/fatcat_web/auth.py index c6e6f04c..0bdb564f 100644 --- a/python/fatcat_web/auth.py +++ b/python/fatcat_web/auth.py @@ -1,18 +1,11 @@ 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, Config +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 auth_api(token): - conf = fatcat_client.Configuration() - conf.api_key["Authorization"] = token - conf.api_key_prefix["Authorization"] = "Bearer" - conf.host = Config.FATCAT_API_HOST - return fatcat_client.DefaultApi(fatcat_client.ApiClient(conf)) - def handle_logout(): logout_user() for k in ('editor', 'token'): @@ -34,35 +27,49 @@ def handle_token_login(token): if not editor_id: abort(400) # fetch editor info - editor = api.get_editor(editor_id).to_dict() + editor = api.get_editor(editor_id) session['api_token'] = token - session['editor'] = editor - login_user(load_user(editor_id)) + 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): - print(remote) - if token: - print(remote.name, token) if user_info: - print(user_info) - print(user_info.iss) - print(user_info.prefered_username) - # fetch api login/signup using user_info - params = AuthOidc(remote.name, user_info.sub, user_info.iss) - resp = api.auth_oidc(params) - editor = resp['editor'] - api_token = resp['token'] + # 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['api_token'] = api_token - session['editor'] = editor.editor_id + session['editor'] = editor.to_dict() # call login_user(load_user(editor_id)) - login_user(load_user(editor_id)) - return redirect("/") + login_user(load_user(editor.editor_id)) + return redirect("/auth/account") raise some_error diff --git a/python/fatcat_web/routes.py b/python/fatcat_web/routes.py index 07947fd5..ebf7e88a 100644 --- a/python/fatcat_web/routes.py +++ b/python/fatcat_web/routes.py @@ -4,8 +4,8 @@ import json 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 -from fatcat_web.auth import handle_token_login, handle_logout, load_user, auth_api +from fatcat_web import app, api, auth_api +from fatcat_web.auth import handle_token_login, handle_logout, load_user from fatcat_client.rest import ApiException from fatcat_web.search import do_search diff --git a/python/fatcat_web/templates/base.html b/python/fatcat_web/templates/base.html index 27b163d2..e3824213 100644 --- a/python/fatcat_web/templates/base.html +++ b/python/fatcat_web/templates/base.html @@ -33,7 +33,7 @@