Example #1
0
def test_authorized_signup_handler(remote, app_rest, models_fixture):
    """Test authorized signup handler."""
    datastore = app_rest.extensions['invenio-accounts'].datastore
    user = datastore.find_user(email='*****@*****.**')

    example_response = {'access_token': 'test_access_token'}

    # Mock remote app's handler
    current_oauthclient.signup_handlers[remote.name] = {
        'setup': lambda token, resp: None
    }

    # Authenticate user
    oauth_authenticate('dev', user)

    # Mock next url
    next_url = '/test/redirect'
    session[token_session_key(remote.name) + '_next_url'] = next_url

    # Check user is redirected to next_url
    expected_url_args = {
        "message": "Successfully authorized.",
        "code": 200,
        "next_url": next_url
    }
    resp = authorized_signup_handler(example_response, remote)
    check_response_redirect_url_args(resp, expected_url_args)
Example #2
0
def authorized_signup_handler(resp, remote, *args, **kwargs):
    """Handle sign-in/up functionality.

    This is needed as we don't use Flask Forms (for now), thus the default
    function would fail.
    """
    # Remove any previously stored auto register session key
    session.pop(token_session_key(remote.name) + '_autoregister', None)

    # Store token in session
    # ----------------------
    # Set token in session - token object only returned if
    # current_user.is_autenticated().
    token = response_token_setter(remote, resp)
    handlers = current_oauthclient.signup_handlers[remote.name]

    # Sign-in/up user
    # ---------------
    if not current_user.is_authenticated:
        account_info = handlers['info'](resp)
        account_info_received.send(remote,
                                   token=token,
                                   response=resp,
                                   account_info=account_info)
        user = oauth_get_user(
            remote.consumer_key,
            account_info=account_info,
            access_token=token_getter(remote)[0],
        )
        if user is None:
            # Auto sign-up if user not found
            user = oauth_register(account_info)

        # Authenticate user
        if not oauth_authenticate(
                remote.consumer_key,
                user,
                require_existing_link=False,
                remember=current_app.config['OAUTHCLIENT_REMOTE_APPS'][
                    remote.name].get('remember', False)):
            return current_app.login_manager.unauthorized()

        # Link account
        # ------------
        # Need to store token in database instead of only the session when
        # called first time.
        token = response_token_setter(remote, resp)

    # Setup account
    # -------------
    if not token.remote_account.extra_data:
        account_setup = handlers['setup'](token, resp)
        account_setup_received.send(remote,
                                    token=token,
                                    response=resp,
                                    account_setup=account_setup)

    return redirect('/')
Example #3
0
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 auth: (onelogin.saml2.auth) Auth object.
    :param remote: (str) Identity provider key.
    :returns: Redirect response.
    """

    # Remove any previously stored auto register session key
    session.pop(token_session_key(remote) + '_autoregister', None)

    # Sign-in/up user
    # ---------------
    if current_user.is_authenticated:
        logout_user()

    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()

        # Fill form with user data
        form = fill_form(form, account_info['user'])

        # Try to register 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()

    # 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'])
Example #4
0
def authorized_signup_handler(resp, remote, *args, **kwargs):
    """Handle sign-in/up functionality.

    This is needed as we don't use Flask Forms (for now), thus the default
    function would fail.
    """
    # Remove any previously stored auto register session key
    session.pop(token_session_key(remote.name) + '_autoregister', None)

    # Store token in session
    # ----------------------
    # Set token in session - token object only returned if
    # current_user.is_autenticated().
    token = response_token_setter(remote, resp)
    handlers = current_oauthclient.signup_handlers[remote.name]

    # Sign-in/up user
    # ---------------
    if not current_user.is_authenticated:
        account_info = handlers['info'](resp)
        account_info_received.send(
            remote, token=token, response=resp, account_info=account_info
        )
        user = oauth_get_user(
            remote.consumer_key,
            account_info=account_info,
            access_token=token_getter(remote)[0],
        )
        if user is None:
            # Auto sign-up if user not found
            user = oauth_register(account_info)

        # Authenticate user
        if not oauth_authenticate(remote.consumer_key, user,
                                  require_existing_link=False):
            return current_app.login_manager.unauthorized()

        # Link account
        # ------------
        # Need to store token in database instead of only the session when
        # called first time.
        token = response_token_setter(remote, resp)

    # Setup account
    # -------------
    if not token.remote_account.extra_data:
        account_setup = handlers['setup'](token, resp)
        account_setup_received.send(
            remote, token=token, response=resp, account_setup=account_setup
        )

    return redirect('/')
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()

    # 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'])
def test_authorized_signup_handler(remote, models_fixture):
    """Test authorized signup handler."""
    datastore = models_fixture.extensions['invenio-accounts'].datastore
    user = datastore.find_user(email='*****@*****.**')

    example_response = {'access_token': 'test_access_token'}

    # Mock remote app's handler
    current_oauthclient.signup_handlers[remote.name] = {
        'setup': lambda token, resp: None
    }

    # Authenticate user
    oauth_authenticate('dev', user)

    # Mock next url
    next_url = '/test/redirect'
    session[token_session_key(remote.name) + '_next_url'] = next_url

    # Check user is redirected to next_url
    resp = authorized_signup_handler(example_response, remote)
    check_redirect_location(resp, next_url)
def test_authorized_signup(app_with_userprofiles, example_orcid, orcid_bio):
    """Test authorized callback with sign-up."""
    app = app_with_userprofiles
    example_data, example_account_info = example_orcid
    example_email = '*****@*****.**'

    with app.test_client() as c:
        # Ensure remote apps have been loaded (due to before first
        # request)
        c.get(url_for('invenio_oauthclient.login', remote_app='orcid'))

        mock_response(app.extensions['oauthlib.client'], 'orcid', example_data)

        # User authorized the requests and is redirect back
        resp = c.get(
            url_for('invenio_oauthclient.authorized',
                    remote_app='orcid',
                    code='test',
                    state=get_state('orcid')))
        assert resp.status_code == 302
        assert resp.location == (
            'http://localhost' +
            url_for('invenio_oauthclient.signup', remote_app='orcid'))

        # User load sign-up page.
        resp = c.get(url_for('invenio_oauthclient.signup', remote_app='orcid'))
        assert resp.status_code == 200

        account_info = session[token_session_key('orcid') + '_account_info']
        data = {
            'email': example_email,
            'password': '******',
            'profile.username': '******',
            'profile.full_name': account_info['user']['profile']['full_name'],
        }

        # Mock request to ORCID to get user bio.
        httpretty.enable()
        httpretty.register_uri(
            httpretty.GET,
            'http://orcid.org/{0}/orcid-bio'.format(example_data['orcid']),
            body=orcid_bio,
            content_type='application/orcid+json; qs=2;charset=UTF-8',
        )

        # User fills form to register
        resp = c.post(
            url_for('invenio_oauthclient.signup', remote_app='orcid'),
            data=data,
        )
        assert resp.status_code == 302
        httpretty.disable()

        # Assert database state (Sign-up complete)
        user = User.query.filter_by(email=example_email).one()
        UserIdentity.query.filter_by(method='orcid',
                                     id_user=user.id,
                                     id=example_data['orcid']).one()
        # FIXME see contrib/orcid.py line 167
        assert user.profile.full_name == 'Josiah Carberry'
        #  assert user.given_names == 'Josiah'
        #  assert user.family_name == 'Carberry'
        # check that the user's email is not yet validated
        assert user.active
        # check that the validation email has been sent
        #  assert hasattr(locmem, 'outbox') and len(locmem.outbox) == 1

        # Disconnect link
        # should not work, because it's the user's only means of login
        resp = c.get(
            url_for('invenio_oauthclient.disconnect', remote_app='orcid'))
        assert resp.status_code == 400

        user = User.query.filter_by(email=example_email).one()
        assert 1 == UserIdentity.query.filter_by(
            method='orcid', id_user=user.id, id=example_data['orcid']).count()

        # set a password for the user
        user.password = hash_password("1234")
        db.session.commit()

        # Disconnect again
        resp = c.get(
            url_for('invenio_oauthclient.disconnect', remote_app='orcid'))
        assert resp.status_code == 302

        # User exists
        user = User.query.filter_by(email=example_email).one()
        # UserIdentity removed.
        assert 0 == UserIdentity.query.filter_by(
            method='orcid', id_user=user.id, id=example_data['orcid']).count()
        assert RemoteAccount.query.filter_by(user_id=user.id).count() == 0
        assert RemoteToken.query.count() == 0
Example #8
0
    def authorized_handler(self, resp, remote, *args, **kwargs):
        """Handle sign-in functionality.

        :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.name) + '_autoregister', None)

        # Store token in session
        # ----------------------
        # Set token in session - token object only returned if
        # current_user.is_autenticated().
        token = response_token_setter(remote, resp)
        handlers = current_oauthclient.signup_handlers[remote.name]

        # Sign-in user
        # ---------------
        if not current_user.is_authenticated:
            account_info = handlers['info'](resp)
            account_info_received.send(remote,
                                       token=token,
                                       response=resp,
                                       account_info=account_info)

            user = oauth_get_user(
                remote.consumer_key,
                account_info=account_info,
                access_token=token_getter(remote)[0],
            )

            # Make sure that external identity either matches
            # or is not yet created (gets created on first oidc login)
            extid = _get_external_id(account_info)
            user_identity: UserIdentity = UserIdentity.query.filter_by(
                id=extid['id'], method=extid['method']).first()
            if user_identity and user_identity.id != extid['id']:
                abort(401)

            if user is None:
                abort(403)

            # Authenticate user
            if not oauth_authenticate(
                    remote.consumer_key, user, require_existing_link=False):
                return current_app.login_manager.unauthorized()

            # Link account
            # ------------
            # Need to store token in database instead of only the session when
            # called first time.
            token = response_token_setter(remote, resp)

        # Setup account
        # -------------
        if not token.remote_account.extra_data:
            account_setup = handlers['setup'](token, resp)
            account_setup_received.send(remote,
                                        token=token,
                                        response=resp,
                                        account_setup=account_setup)
            db.session.commit()
            account_setup_committed.send(remote, token=token)
        else:
            db.session.commit()

        # Redirect to next
        next_url = get_session_next_url(remote.name)
        if next_url:
            return redirect(next_url)
        return redirect(url_for('invenio_oauthclient_settings.index'))
def test_authorized_signup(userprofiles_app, example_orcid, orcid_bio):
    """Test authorized callback with sign-up."""
    app = userprofiles_app
    example_data, example_account_info = example_orcid
    example_email = '*****@*****.**'

    with app.test_client() as c:
        # Ensure remote apps have been loaded (due to before first
        # request)
        c.get(url_for('invenio_oauthclient.login', remote_app='orcid'))

        mock_response(app.extensions['oauthlib.client'], 'orcid', example_data)

        # User authorized the requests and is redirect back
        resp = c.get(
            url_for('invenio_oauthclient.authorized',
                    remote_app='orcid', code='test',
                    state=get_state('orcid')))
        assert resp.status_code == 302
        assert resp.location == (
            'http://localhost' +
            url_for('invenio_oauthclient.signup', remote_app='orcid')
        )

        # User load sign-up page.
        resp = c.get(url_for('invenio_oauthclient.signup', remote_app='orcid'))
        assert resp.status_code == 200

        account_info = session[token_session_key('orcid') + '_account_info']
        data = {
            'email': example_email,
            'password': '******',
            'profile.username': '******',
            'profile.full_name': account_info['user']['profile']['full_name'],
        }

        # Mock request to ORCID to get user bio.
        httpretty.enable()
        httpretty.register_uri(
            httpretty.GET,
            'http://orcid.org/{0}/orcid-bio'.format(example_data['orcid']),
            body=orcid_bio,
            content_type='application/orcid+json; qs=2;charset=UTF-8',
        )

        # User fills form to register
        resp = c.post(
            url_for('invenio_oauthclient.signup', remote_app='orcid'),
            data=data,
        )
        assert resp.status_code == 302
        httpretty.disable()

        # Assert database state (Sign-up complete)
        user = User.query.filter_by(email=example_email).one()
        UserIdentity.query.filter_by(
            method='orcid', id_user=user.id,
            id=example_data['orcid']
        ).one()
        # FIXME see contrib/orcid.py line 167
        assert user.profile.full_name == 'Josiah Carberry'
        #  assert user.given_names == 'Josiah'
        #  assert user.family_name == 'Carberry'
        # check that the user's email is not yet validated
        assert user.active
        # check that the validation email has been sent
        #  assert hasattr(locmem, 'outbox') and len(locmem.outbox) == 1

        # Disconnect link
        resp = c.get(
            url_for('invenio_oauthclient.disconnect', remote_app='orcid'))
        assert resp.status_code == 302

        # User exists
        user = User.query.filter_by(email=example_email).one()
        # UserIdentity removed.
        assert 0 == UserIdentity.query.filter_by(
            method='orcid', id_user=user.id,
            id=example_data['orcid']
        ).count()
        assert RemoteAccount.query.filter_by(user_id=user.id).count() == 0
        assert RemoteToken.query.count() == 0
def cern_authorized_signup_handler(resp, remote, *args, **kwargs):
    """Handle sign-in/up functionality.
    :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.name) + '_autoregister', None)

    # Store token in session
    # ----------------------
    # Set token in session - token object only returned if
    # current_user.is_autenticated().
    token = response_token_setter(remote, resp)
    handlers = current_oauthclient.signup_handlers[remote.name]

    # Sign-in/up user
    # ---------------
    if not current_user.is_authenticated:
        account_info = handlers['info'](resp)
        account_info_received.send(remote,
                                   token=token,
                                   response=resp,
                                   account_info=account_info)

        user = oauth_get_user(
            remote.consumer_key,
            account_info=account_info,
            access_token=token_getter(remote)[0],
        )
        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:
                # requires extra information
                session[token_session_key(remote.name) +
                        '_autoregister'] = True
                session[token_session_key(remote.name) +
                        '_account_info'] = account_info
                session[token_session_key(remote.name) + '_response'] = resp
                db.session.commit()
                return redirect(url_for(
                    '.signup',
                    remote_app=remote.name,
                ))
        # Authenticate user
        if not oauth_authenticate(
                remote.consumer_key, user, require_existing_link=False):
            return current_app.login_manager.unauthorized()

        # Link account
        # ------------
        # Need to store token in database instead of only the session when
        # called first time.
        token = response_token_setter(remote, resp)

    # Setup account
    # -------------
    if not token.remote_account.extra_data:
        account_setup = handlers['setup'](token, resp)
        account_setup_received.send(remote,
                                    token=token,
                                    response=resp,
                                    account_setup=account_setup)
        db.session.commit()
        account_setup_committed.send(remote, token=token)
    else:
        db.session.commit()

    # Redirect to next
    if current_user.is_authenticated and not egroup_admin():
        logout_user()
        return redirect(get_post_logout_redirect())

    next_url = get_session_next_url(remote.name)
    if next_url:
        return redirect(next_url)
    return redirect(url_for('invenio_oauthclient_settings.index'))
Example #11
0
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 auth: (onelogin.saml2.auth) Auth object.
    :param remote: (str) Identity provider key.
    :returns: Redirect response.
    """
    # Remove any previously stored auto register session key
    session.pop(token_session_key(remote) + '_autoregister', None)

    # Sign-in/up user
    # ---------------
    if current_user.is_authenticated:
        logout_user()

    account_info = get_account_info(auth.get_attributes(), remote)

    user = None
    # Pre-check done to use a case insensitive comparison because this is not
    # done in invenio --> https://github.com/inveniosoftware/invenio-oauthclient/blob/master/invenio_oauthclient/utils.py#L82  # nopep8
    if account_info.get('user', {}).get('email'):
        user = User.query.filter(
            func.lower(User.email) == func.lower(account_info['user']
                                                 ['email'])).one_or_none()

    if user is None:
        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()

        # Fill form with user data
        form = fill_form(form, account_info['user'])

        # Try to register 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()

    # 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'])