providers/saml: fix NameIDPolicy not being parsed correctly, improve error handling
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
		@ -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"]
 | 
			
		||||
 | 
			
		||||
@ -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 = {
 | 
			
		||||
 | 
			
		||||
@ -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"""
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user