def login_action(session_info, user): """ Upon successful login in the IdP, store login info in the session and redirect back to the app that asked for authn. :param session_info: the SAML session info :type session_info: dict :param user: the authenticated user :type user: eduid_userdb.User """ current_app.logger.info("User {!r} logging in.".format(user)) session['_saml2_session_name_id'] = code(session_info['name_id']) session['eduPersonPrincipalName'] = user.eppn session['user_eppn'] = user.eppn loa = get_loa(current_app.config.get('AVAILABLE_LOA'), session_info) session['eduPersonAssurance'] = loa session.persist() # redirect the user to the view where he came from relay_state = request.form.get('RelayState', '/') current_app.logger.debug('Redirecting to the RelayState: ' + relay_state) response = redirect(location=relay_state) session.set_cookie(response) current_app.logger.info('Redirecting user {!r} to {!r}'.format( user, relay_state)) return response
def schedule_action(action_key): """ Schedule an action to be executed after an IdP responds to a SAML request. This is called just before the SAML request is sent. :param action_key: the key for the given action :type action_key: str """ logger.debug('Scheduling acs action ' + action_key) session['post-authn-action'] = action_key session.persist()
def _reauthn(reason, session_info, user): current_app.logger.info("Reauthenticating user {!r} for {!r}.".format( user, reason)) session['_saml2_session_name_id'] = code(session_info['name_id']) session[reason] = int(time()) session.persist() # redirect the user to the view where he came from relay_state = request.form.get('RelayState', '/') current_app.logger.debug('Redirecting to the RelayState: ' + relay_state) return redirect(location=relay_state)
def token_login(): current_app.logger.debug('Starting token login') location_on_fail = current_app.config.get( 'TOKEN_LOGIN_FAILURE_REDIRECT_URL') location_on_success = current_app.config.get( 'TOKEN_LOGIN_SUCCESS_REDIRECT_URL') eppn = request.form.get('eppn') token = request.form.get('token') nonce = request.form.get('nonce') timestamp = request.form.get('ts') loa = get_loa(current_app.config.get('AVAILABLE_LOA'), None) # With no session_info lowest loa will be returned if verify_auth_token(eppn=eppn, token=token, nonce=nonce, timestamp=timestamp): try: user = current_app.central_userdb.get_user_by_eppn(eppn) if user.locked_identity.count > 0: # This user has previously verified their account and is not new, this should not happen. current_app.logger.error( 'Not new user {} tried to log in using token login'.format( user)) return redirect(location_on_fail) session['eduPersonPrincipalName'] = user.eppn session['user_eppn'] = user.eppn session['eduPersonAssurance'] = loa session.persist() response = redirect(location_on_success) session.set_cookie(response) current_app.logger.info( 'Successful token login, redirecting user {} to {}'.format( user, location_on_success)) return response except current_app.central_userdb.exceptions.UserDoesNotExist: current_app.logger.error( 'No user with eduPersonPrincipalName = {} found'.format(eppn)) except current_app.central_userdb.exceptions.MultipleUsersReturned: current_app.logger.error( "There are more than one user with eduPersonPrincipalName = {}" .format(eppn)) current_app.logger.info( 'Token login failed, redirecting user to {}'.format(location_on_fail)) return redirect(location_on_fail)
def __call__(self, environ, start_response): next_url = get_current_url(environ) next_path = list(urlparse.urlparse(next_url))[2] whitelist = self.config.get('NO_AUTHN_URLS', []) for regex in whitelist: m = re.match(regex, next_path) if m is not None: return super(AuthnApp, self).__call__(environ, start_response) cookie = parse_cookie(environ) cookie_name = self.config.get('SESSION_COOKIE_NAME') if cookie and cookie_name in cookie: try: return super(AuthnApp, self).__call__(environ, start_response) except NoSessionDataFoundException: del environ['HTTP_COOKIE'] # Force relogin # If HTTP_COOKIE is not removed self.request_context(environ) below # will try to look up the Session data in the backend ts_url = self.config.get('TOKEN_SERVICE_URL') ts_url = urlparse.urljoin(ts_url, 'login') params = {'next': next_url} url_parts = list(urlparse.urlparse(ts_url)) query = urlparse.parse_qs(url_parts[4]) query.update(params) url_parts[4] = urlencode(query) location = urlparse.urlunparse(url_parts) with self.request_context(environ): headers = [('Location', location)] cookie = dump_cookie( cookie_name, session._session.token, max_age=int(self.config.get('PERMANENT_SESSION_LIFETIME')), path=self.config.get('SESSION_COOKIE_PATH'), domain=self.config.get('SESSION_COOKIE_DOMAIN'), secure=self.config.get('SESSION_COOKIE_SECURE'), httponly=self.config.get('SESSION_COOKIE_HTTPONLY')) session.persist() headers.append(('Set-Cookie', cookie)) start_response('302 Found', headers) return []
def login_action(session_info, user): logger.info("User {!r} logging in (eduPersonPrincipalName: {!r})".format( user.user_id, user.eppn)) session['_saml2_session_name_id'] = code(session_info['name_id']) session['eduPersonPrincipalName'] = user.eppn loa = get_loa(current_app.config.get('AVAILABLE_LOA'), session_info) session['eduPersonAssurance'] = loa session.persist() # redirect the user to the view where he came from relay_state = request.form.get('RelayState', '/') logger.debug('Redirecting to the RelayState: ' + relay_state) response = redirect(location=relay_state) session.set_cookie(response) return response
def add_outstanding_query(self, came_from): """ Add a SAML2 authentication query to the queries cache. To be used before accessing the assertion consumer service. :param came_from: url to redirect back the client after finishing with the authn service. :type came_from: str :return: the session token corresponding to the query :rtype: str """ with self.app.test_request_context('/login'): self.app.dispatch_request() oq_cache = OutstandingQueriesCache(session) oq_cache.set(session.token, came_from) session.persist() return session.token
def test_logout_service_startingIDP_no_subject_id(self): eppn = 'hubba-bubba' came_from = '/afterlogin/' session_id = self.add_outstanding_query(came_from) cookie = self.dump_session_cookie(session_id) saml_response = auth_response(session_id, eppn) # Log in through IDP SAMLResponse with self.app.test_request_context('/saml2-acs', method='POST', headers={'Cookie': cookie}, data={ 'SAMLResponse': base64.b64encode(saml_response), 'RelayState': 'testing-relay-state', }): response = self.app.dispatch_request() with self.app.test_request_context('/saml2-ls', method='POST', headers={'Cookie': cookie}, data={ 'SAMLRequest': deflate_and_base64_encode( logout_request(session_id)), 'RelayState': 'testing-relay-state', }): del session['_saml2_session_name_id'] session.persist() response = self.app.dispatch_request() self.assertEqual(response.status, '302 FOUND') self.assertIn('testing-relay-state', response.location)