From fcb795c273826596fb8919824b13936aa2db804b Mon Sep 17 00:00:00 2001 From: Jens Langhammer Date: Thu, 17 Jun 2021 12:22:40 +0200 Subject: [PATCH] providers/saml: fix NameIDPolicy not being parsed correctly, improve error handling Signed-off-by: Jens Langhammer --- .../saml/processors/request_parser.py | 2 +- authentik/providers/saml/views/flows.py | 29 ++++++++++++------- authentik/sources/saml/exceptions.py | 12 +++++--- authentik/stages/authenticator_duo/stage.py | 2 +- 4 files changed, 29 insertions(+), 16 deletions(-) diff --git a/authentik/providers/saml/processors/request_parser.py b/authentik/providers/saml/processors/request_parser.py index f1d9393b3..7cc18e572 100644 --- a/authentik/providers/saml/processors/request_parser.py +++ b/authentik/providers/saml/processors/request_parser.py @@ -69,7 +69,7 @@ class AuthNRequestParser: auth_n_request = AuthNRequest(id=root.attrib["ID"], relay_state=relay_state) # Check if AuthnRequest has a NameID Policy object - name_id_policies = root.findall(f"{{{NS_SAML_PROTOCOL}}}:NameIDPolicy") + name_id_policies = root.findall(f"{{{NS_SAML_PROTOCOL}}}NameIDPolicy") if len(name_id_policies) > 0: name_id_policy = name_id_policies[0] auth_n_request.name_id_policy = name_id_policy.attrib["Format"] diff --git a/authentik/providers/saml/views/flows.py b/authentik/providers/saml/views/flows.py index 803ff6d19..f7f4c13de 100644 --- a/authentik/providers/saml/views/flows.py +++ b/authentik/providers/saml/views/flows.py @@ -17,6 +17,7 @@ from authentik.providers.saml.models import SAMLBindings, SAMLProvider from authentik.providers.saml.processors.assertion import AssertionProcessor from authentik.providers.saml.processors.request_parser import AuthNRequest from authentik.providers.saml.utils.encoding import deflate_and_base64_encode, nice64 +from authentik.sources.saml.exceptions import SAMLException LOGGER = get_logger() URL_VALIDATOR = URLValidator(schemes=("http", "https")) @@ -56,22 +57,30 @@ class SAMLFlowFinalView(ChallengeStageView): provider: SAMLProvider = get_object_or_404( SAMLProvider, pk=application.provider_id ) - # Log Application Authorization - Event.new( - EventAction.AUTHORIZE_APPLICATION, - authorized_application=application, - flow=self.executor.plan.flow_pk, - ).from_http(self.request) - if SESSION_KEY_AUTH_N_REQUEST not in self.request.session: return self.executor.stage_invalid() auth_n_request: AuthNRequest = self.request.session.pop( SESSION_KEY_AUTH_N_REQUEST ) - response = AssertionProcessor( - provider, request, auth_n_request - ).build_response() + try: + response = AssertionProcessor( + provider, request, auth_n_request + ).build_response() + except SAMLException as exc: + Event.new( + EventAction.CONFIGURATION_ERROR, + message=f"Failed to process SAML assertion: {str(exc)}", + provider=provider, + ).from_http(self.request) + return self.executor.stage_invalid() + + # Log Application Authorization + Event.new( + EventAction.AUTHORIZE_APPLICATION, + authorized_application=application, + flow=self.executor.plan.flow_pk, + ).from_http(self.request) if provider.sp_binding == SAMLBindings.POST: form_attrs = { diff --git a/authentik/sources/saml/exceptions.py b/authentik/sources/saml/exceptions.py index 09f7afbff..344ee005b 100644 --- a/authentik/sources/saml/exceptions.py +++ b/authentik/sources/saml/exceptions.py @@ -2,17 +2,21 @@ from authentik.lib.sentry import SentryIgnoredException -class MissingSAMLResponse(SentryIgnoredException): +class SAMLException(SentryIgnoredException): + """Base SAML Exception""" + + +class MissingSAMLResponse(SAMLException): """Exception raised when request does not contain SAML Response.""" -class UnsupportedNameIDFormat(SentryIgnoredException): +class UnsupportedNameIDFormat(SAMLException): """Exception raised when SAML Response contains NameID Format not supported.""" -class MismatchedRequestID(SentryIgnoredException): +class MismatchedRequestID(SAMLException): """Exception raised when the returned request ID doesn't match the saved ID.""" -class InvalidSignature(SentryIgnoredException): +class InvalidSignature(SAMLException): """Signature of XML Object is either missing or invalid""" diff --git a/authentik/stages/authenticator_duo/stage.py b/authentik/stages/authenticator_duo/stage.py index 6007ad9c2..abca61479 100644 --- a/authentik/stages/authenticator_duo/stage.py +++ b/authentik/stages/authenticator_duo/stage.py @@ -51,7 +51,7 @@ class AuthenticatorDuoStageView(ChallengeStageView): EventAction.CONFIGURATION_ERROR, message=f"Failed to enroll user: {str(exc)}", user=user, - ).from_http(self.request).set_user(user).save() + ).from_http(self.request, user) raise InvalidStageError(str(exc)) from exc user_id = enroll["user_id"] self.request.session[SESSION_KEY_DUO_USER_ID] = user_id