From d086317b337df1d379c0a7bc548b2da92237b99a Mon Sep 17 00:00:00 2001 From: Valentin Deniaud Date: Tue, 16 Apr 2019 10:14:23 +0200 Subject: [PATCH 6/7] idp_saml: handle authentication level increase request --- src/authentic2/idp/saml/saml2_endpoints.py | 27 +++++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/authentic2/idp/saml/saml2_endpoints.py b/src/authentic2/idp/saml/saml2_endpoints.py index 1274dad4..030c7552 100644 --- a/src/authentic2/idp/saml/saml2_endpoints.py +++ b/src/authentic2/idp/saml/saml2_endpoints.py @@ -531,16 +531,20 @@ def sso(request): return sso_after_process_request(request, login, nid_format=nid_format) -def need_login(request, login, nid_format, service): +def need_login(request, login, nid_format, service, auth_level=None): """Redirect to the login page with a nonce parameter to verify later that the login form was submitted """ nonce = login.request.id or get_nonce() save_key_values(nonce, login.dump(), False, nid_format) - next_url = make_url(continue_sso, params={NONCE_FIELD_NAME: nonce}) + params = { + NONCE_FIELD_NAME: nonce + } + next_url = make_url(continue_sso, params=params) + if auth_level: + params['auth_level'] = auth_level logger.debug('redirect to login page with next url %s', next_url) - return login_require(request, next_url=next_url, params={NONCE_FIELD_NAME: nonce}, - service=service) + return login_require(request, next_url=next_url, params=params, service=service) def get_url_with_nonce(request, function, nonce): @@ -642,6 +646,11 @@ def sso_after_process_request(request, login, consent_obtained=False, did_auth = find_authentication_event(request, nonce) is not None force_authn = login.request.forceAuthn passive = login.request.isPassive + requested_auth_level = False + if login.request.requestedAuthnContext: + authn_classref = login.request.requestedAuthnContext.authnContextClassRef + if authn_classref and app_settings.AUTH_LEVELS_MAPPING.get(authn_classref[0]): + requested_auth_level = app_settings.AUTH_LEVELS_MAPPING[authn_classref[0]] logger.debug('NameIDFormat is %s', nid_format) logger.debug('nonce is %s', nonce) @@ -650,13 +659,19 @@ def sso_after_process_request(request, login, consent_obtained=False, service = LibertyServiceProvider.objects.get( liberty_provider__entity_id=login.remoteProviderId).liberty_provider + current_auth_level = request.session.get('auth_level', 1) + if not user.is_anonymous() and requested_auth_level > current_auth_level: + requested_auth_level = current_auth_level + 1 # progressively increase auth level + return need_login(request, login, nid_format, service, requested_auth_level) + if not passive and \ (user.is_anonymous() or (force_authn and not did_auth)): logger.debug('login required') return need_login(request, login, nid_format, service) - # No user is authenticated and passive is True, deny request - if passive and user.is_anonymous(): + # No user is authenticated or authentication level is too low and passive + # is True, deny request + if passive and (user.is_anonymous() or requested_auth_level > current_auth_level): logger.debug('no user connected and passive request, returning NoPassive') set_saml2_response_responder_status_code(login.response, lasso.SAML2_STATUS_CODE_NO_PASSIVE) -- 2.20.1