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:
Jens Langhammer 2021-06-17 12:22:40 +02:00
parent 14c70b3e4a
commit fcb795c273
4 changed files with 29 additions and 16 deletions

View File

@ -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"]

View File

@ -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 = {

View File

@ -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"""

View File

@ -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