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