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) auth_n_request = AuthNRequest(id=root.attrib["ID"], relay_state=relay_state)
# Check if AuthnRequest has a NameID Policy object # 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: if len(name_id_policies) > 0:
name_id_policy = name_id_policies[0] name_id_policy = name_id_policies[0]
auth_n_request.name_id_policy = name_id_policy.attrib["Format"] 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.assertion import AssertionProcessor
from authentik.providers.saml.processors.request_parser import AuthNRequest from authentik.providers.saml.processors.request_parser import AuthNRequest
from authentik.providers.saml.utils.encoding import deflate_and_base64_encode, nice64 from authentik.providers.saml.utils.encoding import deflate_and_base64_encode, nice64
from authentik.sources.saml.exceptions import SAMLException
LOGGER = get_logger() LOGGER = get_logger()
URL_VALIDATOR = URLValidator(schemes=("http", "https")) URL_VALIDATOR = URLValidator(schemes=("http", "https"))
@ -56,22 +57,30 @@ class SAMLFlowFinalView(ChallengeStageView):
provider: SAMLProvider = get_object_or_404( provider: SAMLProvider = get_object_or_404(
SAMLProvider, pk=application.provider_id 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: if SESSION_KEY_AUTH_N_REQUEST not in self.request.session:
return self.executor.stage_invalid() return self.executor.stage_invalid()
auth_n_request: AuthNRequest = self.request.session.pop( auth_n_request: AuthNRequest = self.request.session.pop(
SESSION_KEY_AUTH_N_REQUEST SESSION_KEY_AUTH_N_REQUEST
) )
response = AssertionProcessor( try:
provider, request, auth_n_request response = AssertionProcessor(
).build_response() 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: if provider.sp_binding == SAMLBindings.POST:
form_attrs = { form_attrs = {

View File

@ -2,17 +2,21 @@
from authentik.lib.sentry import SentryIgnoredException 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.""" """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.""" """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.""" """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""" """Signature of XML Object is either missing or invalid"""

View File

@ -51,7 +51,7 @@ class AuthenticatorDuoStageView(ChallengeStageView):
EventAction.CONFIGURATION_ERROR, EventAction.CONFIGURATION_ERROR,
message=f"Failed to enroll user: {str(exc)}", message=f"Failed to enroll user: {str(exc)}",
user=user, user=user,
).from_http(self.request).set_user(user).save() ).from_http(self.request, user)
raise InvalidStageError(str(exc)) from exc raise InvalidStageError(str(exc)) from exc
user_id = enroll["user_id"] user_id = enroll["user_id"]
self.request.session[SESSION_KEY_DUO_USER_ID] = user_id self.request.session[SESSION_KEY_DUO_USER_ID] = user_id