# Copyright (c) 2019. Tobias Kurze """ OIDC login auth module """ from datetime import datetime import flask from flask import jsonify, redirect, url_for from flask_login import login_user from flask_pyoidc.flask_pyoidc import OIDCAuthentication from flask_pyoidc.user_session import UserSession from backend import app, db from backend.models.user_model import User from . import auth_bp from .oidc_config import PROVIDER_NAME, OIDC_PROVIDERS OIDCAuthentication.oidc_auth_orig = OIDCAuthentication.oidc_auth OIDCAuthentication.oidc_logout_orig = OIDCAuthentication.oidc_logout ''' def oidc_auth_default_provider(self): """monkey patch oidc_auth""" return self.oidc_auth_orig(PROVIDER_NAME) def oidc_logout_default_provider(self): """monkey patch oidc_logout""" return self.oidc_logout_orig(PROVIDER_NAME) OIDCAuthentication.oidc_auth = oidc_auth_default_provider OIDCAuthentication.oidc_logout = oidc_logout_default_provider ''' oidc_auth = OIDCAuthentication(OIDC_PROVIDERS) def create_or_retrieve_user_from_userinfo(userinfo): """Updates and returns ar creates a user from userinfo (part of OIDC token).""" try: email = userinfo["email"] except KeyError: app.logger.error("email is missing in OIDC userinfo! Can't create user!") return None user = User.get_by_identifier(email) if user is not None: app.logger.info("user found") app.logger.debug(f"user found: {email}") user.last_seen = datetime.utcnow() # TODO: update user! db.session.commit() return user user = User(email=email, first_name=userinfo.get("given_name", ""), last_name=userinfo.get("family_name", "")) app.logger.info(f"creating new user: {email}") db.session.add(user) db.session.commit() return user @auth_bp.route('/oidc', methods=['GET']) @oidc_auth.oidc_auth(provider_name=PROVIDER_NAME) def oidc(): user_session = UserSession(flask.session) app.logger.info(user_session.userinfo) user = create_or_retrieve_user_from_userinfo(user_session.userinfo) if user is None: return '' login_user(user) app.logger.info(f"logged in user: {str(user)}") app.logger.debug(f"id token: {str(user_session.id_token)}") return jsonify(id_token=user_session.id_token, access_token=flask.session['access_token'], userinfo=user_session.userinfo) @auth_bp.route('/oidc_logout', methods=['GET']) @oidc_auth.oidc_logout def oidc_logout(): # oidc_auth.oidc_logout() app.logger.debug("Logging out current user!") return redirect('/') @oidc_auth.error_view def error(error=None, error_description=None): app.logger.error(f"Something wwent wrong with OIDC auth – error: {error}, message: {error_description}") return jsonify({'error': error, 'message': error_description})