Source code for shibboleth_authenticator.handlers

# -*- coding: utf-8 -*-
#
# This file is part of the shibboleth-authenticator module for Invenio.
# Copyright (C) 2017  Helmholtz-Zentrum Dresden-Rossendorf
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

"""Handlers for shibboleth endpoints."""

from __future__ import absolute_import, print_function

from flask import current_app, redirect, session
from flask_login import current_user
from invenio_db import db
from invenio_oauthclient.errors import AlreadyLinkedError
from invenio_oauthclient.handlers import (get_session_next_url,
                                          oauth_error_handler,
                                          token_session_key)
from invenio_oauthclient.utils import (create_csrf_disabled_registrationform,
                                       fill_form, oauth_authenticate,
                                       oauth_get_user, oauth_link_external_id,
                                       oauth_register)
from werkzeug.local import LocalProxy

from .utils import get_account_info

_security = LocalProxy(lambda: current_app.extensions['security'])

_datastore = LocalProxy(lambda: _security.datastore)


#
# Handlers
#
[docs]@oauth_error_handler def authorized_signup_handler(auth, remote=None, *args, **kwargs): """ Handle sign-in/up functionality. Checks if user is already registered. If not registered, the function registers a new user and authenticates the new user. If there already exists a user object in the database, the user is only authenticated and logged in. :param remote: The remote application. :param resp: The response. :returns: Redirect response. """ # Remove any previously stored auto register session key session.pop(token_session_key(remote) + '_autoregister', None) # Sign-in/up user # --------------- if not current_user.is_authenticated: account_info = get_account_info(auth.get_attributes(), remote) user = oauth_get_user( remote, account_info=account_info ) if user is None: # Auto sign-up if user not found form = create_csrf_disabled_registrationform() form = fill_form( form, account_info['user'] ) user = oauth_register(form) # if registration fails ... if user is None: return current_app.login_manager.unauthorized() # Authenticate user if not oauth_authenticate(remote, user, require_existing_link=False): return current_app.login_manager.unauthorized() db.session.commit() # create external id link try: oauth_link_external_id( user, dict( id=account_info['external_id'], method=remote) ) db.session.commit() except AlreadyLinkedError: pass # Redirect to next next_url = get_session_next_url(remote) if next_url: return redirect(next_url) return redirect(current_app.config['SECURITY_POST_LOGIN_VIEW'])