authentik.providers.saml.processors.logout_request_parser
LogoutRequest parser
1"""LogoutRequest parser""" 2 3from base64 import b64decode 4from dataclasses import dataclass 5 6from defusedxml import ElementTree 7 8from authentik.common.saml.constants import NS_SAML_ASSERTION, NS_SAML_PROTOCOL 9from authentik.providers.saml.exceptions import CannotHandleAssertion 10from authentik.providers.saml.models import SAMLProvider 11from authentik.providers.saml.processors.authn_request_parser import ERROR_CANNOT_DECODE_REQUEST 12from authentik.providers.saml.utils.encoding import decode_base64_and_inflate 13 14 15@dataclass(slots=True) 16class LogoutRequest: 17 """Logout Request""" 18 19 id: str | None = None 20 21 issuer: str | None = None 22 23 name_id: str | None = None 24 25 name_id_format: str | None = None 26 27 session_index: str | None = None 28 29 relay_state: str | None = None 30 31 32class LogoutRequestParser: 33 """LogoutRequest Parser""" 34 35 provider: SAMLProvider 36 37 def __init__(self, provider: SAMLProvider): 38 self.provider = provider 39 40 def _parse_xml(self, decoded_xml: str | bytes, relay_state: str | None = None) -> LogoutRequest: 41 root = ElementTree.fromstring(decoded_xml) 42 request = LogoutRequest( 43 id=root.attrib["ID"], 44 ) 45 # Try both namespaces for Issuer 46 issuers = root.findall(f"{{{NS_SAML_PROTOCOL}}}Issuer") 47 if not issuers: 48 issuers = root.findall(f"{{{NS_SAML_ASSERTION}}}Issuer") 49 if len(issuers) > 0: 50 request.issuer = issuers[0].text 51 52 # Extract NameID 53 name_ids = root.findall(f"{{{NS_SAML_ASSERTION}}}NameID") 54 if not name_ids: 55 name_ids = root.findall(f"{{{NS_SAML_PROTOCOL}}}NameID") 56 if len(name_ids) > 0: 57 request.name_id = name_ids[0].text 58 # Extract NameID Format if present 59 if "Format" in name_ids[0].attrib: 60 request.name_id_format = name_ids[0].attrib["Format"] 61 62 # Extract SessionIndex 63 session_indexes = root.findall(f"{{{NS_SAML_PROTOCOL}}}SessionIndex") 64 if not session_indexes: 65 session_indexes = root.findall(f"{{{NS_SAML_ASSERTION}}}SessionIndex") 66 if len(session_indexes) > 0: 67 request.session_index = session_indexes[0].text 68 69 request.relay_state = relay_state 70 return request 71 72 def parse(self, saml_request: str, relay_state: str | None = None) -> LogoutRequest: 73 """Validate and parse raw request with enveloped signautre.""" 74 try: 75 decoded_xml = b64decode(saml_request.encode()) 76 except UnicodeDecodeError: 77 raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) from None 78 return self._parse_xml(decoded_xml, relay_state) 79 80 def parse_detached( 81 self, 82 saml_request: str, 83 relay_state: str | None = None, 84 ) -> LogoutRequest: 85 """Validate and parse raw request with detached signature""" 86 try: 87 decoded_xml = decode_base64_and_inflate(saml_request) 88 except UnicodeDecodeError: 89 raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) from None 90 91 return self._parse_xml(decoded_xml, relay_state)
@dataclass(slots=True)
class
LogoutRequest:
16@dataclass(slots=True) 17class LogoutRequest: 18 """Logout Request""" 19 20 id: str | None = None 21 22 issuer: str | None = None 23 24 name_id: str | None = None 25 26 name_id_format: str | None = None 27 28 session_index: str | None = None 29 30 relay_state: str | None = None
Logout Request
class
LogoutRequestParser:
33class LogoutRequestParser: 34 """LogoutRequest Parser""" 35 36 provider: SAMLProvider 37 38 def __init__(self, provider: SAMLProvider): 39 self.provider = provider 40 41 def _parse_xml(self, decoded_xml: str | bytes, relay_state: str | None = None) -> LogoutRequest: 42 root = ElementTree.fromstring(decoded_xml) 43 request = LogoutRequest( 44 id=root.attrib["ID"], 45 ) 46 # Try both namespaces for Issuer 47 issuers = root.findall(f"{{{NS_SAML_PROTOCOL}}}Issuer") 48 if not issuers: 49 issuers = root.findall(f"{{{NS_SAML_ASSERTION}}}Issuer") 50 if len(issuers) > 0: 51 request.issuer = issuers[0].text 52 53 # Extract NameID 54 name_ids = root.findall(f"{{{NS_SAML_ASSERTION}}}NameID") 55 if not name_ids: 56 name_ids = root.findall(f"{{{NS_SAML_PROTOCOL}}}NameID") 57 if len(name_ids) > 0: 58 request.name_id = name_ids[0].text 59 # Extract NameID Format if present 60 if "Format" in name_ids[0].attrib: 61 request.name_id_format = name_ids[0].attrib["Format"] 62 63 # Extract SessionIndex 64 session_indexes = root.findall(f"{{{NS_SAML_PROTOCOL}}}SessionIndex") 65 if not session_indexes: 66 session_indexes = root.findall(f"{{{NS_SAML_ASSERTION}}}SessionIndex") 67 if len(session_indexes) > 0: 68 request.session_index = session_indexes[0].text 69 70 request.relay_state = relay_state 71 return request 72 73 def parse(self, saml_request: str, relay_state: str | None = None) -> LogoutRequest: 74 """Validate and parse raw request with enveloped signautre.""" 75 try: 76 decoded_xml = b64decode(saml_request.encode()) 77 except UnicodeDecodeError: 78 raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) from None 79 return self._parse_xml(decoded_xml, relay_state) 80 81 def parse_detached( 82 self, 83 saml_request: str, 84 relay_state: str | None = None, 85 ) -> LogoutRequest: 86 """Validate and parse raw request with detached signature""" 87 try: 88 decoded_xml = decode_base64_and_inflate(saml_request) 89 except UnicodeDecodeError: 90 raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) from None 91 92 return self._parse_xml(decoded_xml, relay_state)
LogoutRequest Parser
LogoutRequestParser(provider: authentik.providers.saml.models.SAMLProvider)
73 def parse(self, saml_request: str, relay_state: str | None = None) -> LogoutRequest: 74 """Validate and parse raw request with enveloped signautre.""" 75 try: 76 decoded_xml = b64decode(saml_request.encode()) 77 except UnicodeDecodeError: 78 raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) from None 79 return self._parse_xml(decoded_xml, relay_state)
Validate and parse raw request with enveloped signautre.
81 def parse_detached( 82 self, 83 saml_request: str, 84 relay_state: str | None = None, 85 ) -> LogoutRequest: 86 """Validate and parse raw request with detached signature""" 87 try: 88 decoded_xml = decode_base64_and_inflate(saml_request) 89 except UnicodeDecodeError: 90 raise CannotHandleAssertion(ERROR_CANNOT_DECODE_REQUEST) from None 91 92 return self._parse_xml(decoded_xml, relay_state)
Validate and parse raw request with detached signature