def is_valid(self, request_data, request_id=None, raise_exceptions=False): """ Determines if the SAML LogoutResponse is valid :param request_id: The ID of the LogoutRequest sent by this SP to the IdP :type request_id: string :param raise_exceptions: Whether to return false on failure or raise an exception :type raise_exceptions: Boolean :return: Returns if the SAML LogoutResponse is or not valid :rtype: boolean """ self.__error = None lowercase_urlencoding = False try: idp_data = self.__settings.get_idp_data() idp_entity_id = idp_data['entityId'] get_data = request_data['get_data'] if 'lowercase_urlencoding' in request_data.keys(): lowercase_urlencoding = request_data['lowercase_urlencoding'] if self.__settings.is_strict(): res = OneLogin_Saml2_Utils.validate_xml(self.document, 'saml-schema-protocol-2.0.xsd', self.__settings.is_debug_active()) if not isinstance(res, Document): raise OneLogin_Saml2_ValidationError( 'Invalid SAML Logout Response. Not match the saml-schema-protocol-2.0.xsd', OneLogin_Saml2_ValidationError.INVALID_XML_FORMAT ) security = self.__settings.get_security_data() # Check if the InResponseTo of the Logout Response matches the ID of the Logout Request (requestId) if provided if request_id is not None and self.document.documentElement.hasAttribute('InResponseTo'): in_response_to = self.document.documentElement.getAttribute('InResponseTo') if request_id != in_response_to: raise OneLogin_Saml2_ValidationError( 'The InResponseTo of the Logout Response: %s, does not match the ID of the Logout request sent by the SP: %s' % (in_response_to, request_id), OneLogin_Saml2_ValidationError.WRONG_INRESPONSETO ) # Check issuer issuer = self.get_issuer() if issuer is not None and issuer != idp_entity_id: raise OneLogin_Saml2_ValidationError( 'Invalid issuer in the Logout Request', OneLogin_Saml2_ValidationError.WRONG_ISSUER ) current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data) # Check destination if self.document.documentElement.hasAttribute('Destination'): destination = self.document.documentElement.getAttribute('Destination') if destination != '': if current_url not in destination: raise OneLogin_Saml2_ValidationError( 'The LogoutResponse was received at %s instead of %s' % (current_url, destination), OneLogin_Saml2_ValidationError.WRONG_DESTINATION ) if security['wantMessagesSigned']: if security['wantValidMessageSignature']: if 'Signature' not in get_data: raise OneLogin_Saml2_ValidationError( 'The Message of the Logout Response is not signed and the SP require it', OneLogin_Saml2_ValidationError.NO_SIGNED_MESSAGE ) if 'Signature' in get_data: if 'SigAlg' not in get_data: sign_alg = OneLogin_Saml2_Constants.RSA_SHA1 else: sign_alg = get_data['SigAlg'] signed_query = 'SAMLResponse=%s' % OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'SAMLResponse', lowercase_urlencoding=lowercase_urlencoding) if 'RelayState' in get_data: signed_query = '%s&RelayState=%s' % (signed_query, OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'RelayState', lowercase_urlencoding=lowercase_urlencoding)) signed_query = '%s&SigAlg=%s' % (signed_query, OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'SigAlg', OneLogin_Saml2_Constants.RSA_SHA1, lowercase_urlencoding=lowercase_urlencoding)) exists_x509cert = 'x509cert' in idp_data and idp_data['x509cert'] exists_multix509sign = 'x509certMulti' in idp_data and \ 'signing' in idp_data['x509certMulti'] and \ idp_data['x509certMulti']['signing'] if not (exists_x509cert or exists_multix509sign): raise OneLogin_Saml2_Error( 'In order to validate the sign on the Logout Response, the x509cert of the IdP is required', OneLogin_Saml2_Error.CERT_NOT_FOUND ) if exists_multix509sign: for cert in idp_data['x509certMulti']['signing']: if OneLogin_Saml2_Utils.validate_binary_sign(signed_query, b64decode(get_data['Signature']), cert, sign_alg): return True raise OneLogin_Saml2_ValidationError( 'Signature validation failed. Logout Response rejected', OneLogin_Saml2_ValidationError.INVALID_SIGNATURE ) else: cert = idp_data['x509cert'] if not OneLogin_Saml2_Utils.validate_binary_sign(signed_query, b64decode(get_data['Signature']), cert, sign_alg): raise OneLogin_Saml2_ValidationError( 'Signature validation failed. Logout Response rejected', OneLogin_Saml2_ValidationError.INVALID_SIGNATURE ) return True # pylint: disable=R0801 except Exception as err: self.__error = err.__str__() debug = self.__settings.is_debug_active() if debug: print err.__str__() if raise_exceptions: raise err return False
def is_valid(self, request_data): """ Checks if the Logout Request received is valid :param request_data: Request Data :type request_data: dict :return: If the Logout Request is or not valid :rtype: boolean """ self.__error = None lowercase_urlencoding = False try: dom = fromstring(self.__logout_request) idp_data = self.__settings.get_idp_data() idp_entity_id = idp_data['entityId'] if 'get_data' in request_data.keys(): get_data = request_data['get_data'] else: get_data = {} if 'lowercase_urlencoding' in request_data.keys(): lowercase_urlencoding = request_data['lowercase_urlencoding'] if self.__settings.is_strict(): res = OneLogin_Saml2_Utils.validate_xml(dom, 'saml-schema-protocol-2.0.xsd', self.__settings.is_debug_active()) if not isinstance(res, Document): raise Exception('Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd') security = self.__settings.get_security_data() current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data) # Check NotOnOrAfter if dom.get('NotOnOrAfter', None): na = OneLogin_Saml2_Utils.parse_SAML_to_time(dom.get('NotOnOrAfter')) if na <= OneLogin_Saml2_Utils.now(): raise Exception('Timing issues (please check your clock settings)') # Check destination if dom.get('Destination', None): destination = dom.get('Destination') if destination != '': if current_url not in destination: raise Exception( 'The LogoutRequest was received at ' '%(currentURL)s instead of %(destination)s' % { 'currentURL': current_url, 'destination': destination, } ) # Check issuer issuer = OneLogin_Saml2_Logout_Request.get_issuer(dom) if issuer is not None and issuer != idp_entity_id: raise Exception('Invalid issuer in the Logout Request') if security['wantMessagesSigned']: if 'Signature' not in get_data: raise Exception('The Message of the Logout Request is not signed and the SP require it') if 'Signature' in get_data: if 'SigAlg' not in get_data: sign_alg = OneLogin_Saml2_Constants.RSA_SHA1 else: sign_alg = get_data['SigAlg'] signed_query = 'SAMLRequest=%s' % OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'SAMLRequest', lowercase_urlencoding=lowercase_urlencoding) if 'RelayState' in get_data: signed_query = '%s&RelayState=%s' % (signed_query, OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'RelayState', lowercase_urlencoding=lowercase_urlencoding)) signed_query = '%s&SigAlg=%s' % (signed_query, OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'SigAlg', OneLogin_Saml2_Constants.RSA_SHA1, lowercase_urlencoding=lowercase_urlencoding)) if 'x509cert' not in idp_data or idp_data['x509cert'] is None: raise Exception('In order to validate the sign on the Logout Request, the x509cert of the IdP is required') cert = idp_data['x509cert'] if not OneLogin_Saml2_Utils.validate_binary_sign(signed_query, b64decode(get_data['Signature']), cert, sign_alg): raise Exception('Signature validation failed. Logout Request rejected') return True except Exception as err: # pylint: disable=R0801sign_alg self.__error = err.__str__() debug = self.__settings.is_debug_active() if debug: print err.__str__() return False
def is_valid(self, request_data, request_id=None): """ Determines if the SAML LogoutResponse is valid :param request_id: The ID of the LogoutRequest sent by this SP to the IdP :type request_id: string :return: Returns if the SAML LogoutResponse is or not valid :rtype: boolean """ self.__error = None lowercase_urlencoding = False try: idp_data = self.__settings.get_idp_data() idp_entity_id = idp_data['entityId'] get_data = request_data['get_data'] if 'lowercase_urlencoding' in request_data.keys(): lowercase_urlencoding = request_data['lowercase_urlencoding'] if self.__settings.is_strict(): res = OneLogin_Saml2_Utils.validate_xml( self.document, 'saml-schema-protocol-2.0.xsd', self.__settings.is_debug_active()) if not isinstance(res, Document): raise Exception( 'Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd' ) security = self.__settings.get_security_data() # Check if the InResponseTo of the Logout Response matches the ID of the Logout Request (requestId) if provided if request_id is not None and self.document.documentElement.hasAttribute( 'InResponseTo'): in_response_to = self.document.documentElement.getAttribute( 'InResponseTo') if request_id != in_response_to: raise Exception( 'The InResponseTo of the Logout Response: %s, does not match the ID of the Logout request sent by the SP: %s' % (in_response_to, request_id)) # Check issuer issuer = self.get_issuer() if issuer is not None and issuer != idp_entity_id: raise Exception('Invalid issuer in the Logout Request') current_url = OneLogin_Saml2_Utils.get_self_url_no_query( request_data) # Check destination if self.document.documentElement.hasAttribute('Destination'): destination = self.document.documentElement.getAttribute( 'Destination') if destination != '': if current_url not in destination: raise Exception( 'The LogoutRequest was received at $currentURL instead of $destination' ) if security['wantMessagesSigned']: if 'Signature' not in get_data: raise Exception( 'The Message of the Logout Response is not signed and the SP require it' ) if 'Signature' in get_data: if 'SigAlg' not in get_data: sign_alg = OneLogin_Saml2_Constants.RSA_SHA1 else: sign_alg = get_data['SigAlg'] signed_query = 'SAMLResponse=%s' % OneLogin_Saml2_Utils.get_encoded_parameter( get_data, 'SAMLResponse', lowercase_urlencoding=lowercase_urlencoding) if 'RelayState' in get_data: signed_query = '%s&RelayState=%s' % ( signed_query, OneLogin_Saml2_Utils.get_encoded_parameter( get_data, 'RelayState', lowercase_urlencoding=lowercase_urlencoding)) signed_query = '%s&SigAlg=%s' % ( signed_query, OneLogin_Saml2_Utils.get_encoded_parameter( get_data, 'SigAlg', OneLogin_Saml2_Constants.RSA_SHA1, lowercase_urlencoding=lowercase_urlencoding)) if 'x509cert' not in idp_data or idp_data['x509cert'] is None: raise Exception( 'In order to validate the sign on the Logout Response, the x509cert of the IdP is required' ) cert = idp_data['x509cert'] if not OneLogin_Saml2_Utils.validate_binary_sign( signed_query, b64decode(get_data['Signature']), cert, sign_alg): raise Exception( 'Signature validation failed. Logout Response rejected' ) return True # pylint: disable=R0801 except Exception as err: self.__error = err.__str__() debug = self.__settings.is_debug_active() if debug: print err.__str__() return False
def is_valid(self, request_data, raise_exceptions=False): """ Checks if the Logout Request received is valid :param request_data: Request Data :type request_data: dict :param raise_exceptions: Whether to return false on failure or raise an exception :type raise_exceptions: Boolean :return: If the Logout Request is or not valid :rtype: boolean """ self.__error = None lowercase_urlencoding = False try: dom = fromstring(self.__logout_request, forbid_dtd=True) idp_data = self.__settings.get_idp_data() idp_entity_id = idp_data['entityId'] if 'get_data' in request_data.keys(): get_data = request_data['get_data'] else: get_data = {} if 'lowercase_urlencoding' in request_data.keys(): lowercase_urlencoding = request_data['lowercase_urlencoding'] if self.__settings.is_strict(): res = OneLogin_Saml2_Utils.validate_xml( dom, 'saml-schema-protocol-2.0.xsd', self.__settings.is_debug_active()) if not isinstance(res, Document): raise OneLogin_Saml2_ValidationError( 'Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd', OneLogin_Saml2_ValidationError.INVALID_XML_FORMAT) security = self.__settings.get_security_data() current_url = OneLogin_Saml2_Utils.get_self_url_no_query( request_data) # Check NotOnOrAfter if dom.get('NotOnOrAfter', None): na = OneLogin_Saml2_Utils.parse_SAML_to_time( dom.get('NotOnOrAfter')) if na <= OneLogin_Saml2_Utils.now(): raise OneLogin_Saml2_ValidationError( 'Could not validate timestamp: expired. Check system clock.', OneLogin_Saml2_ValidationError.RESPONSE_EXPIRED) # Check destination destination = dom.get('Destination') if destination: if not OneLogin_Saml2_Utils.normalize_url( url=destination).startswith( OneLogin_Saml2_Utils.normalize_url( url=current_url)): raise Exception( 'The LogoutRequest was received at ' '%(currentURL)s instead of %(destination)s' % { 'currentURL': current_url, 'destination': destination, }, OneLogin_Saml2_ValidationError.WRONG_DESTINATION) # Check issuer issuer = OneLogin_Saml2_Logout_Request.get_issuer(dom) if issuer is not None and issuer != idp_entity_id: raise OneLogin_Saml2_ValidationError( 'Invalid issuer in the Logout Request (expected %(idpEntityId)s, got %(issuer)s)' % { 'idpEntityId': idp_entity_id, 'issuer': issuer }, OneLogin_Saml2_ValidationError.WRONG_ISSUER) if security['wantMessagesSigned']: if 'Signature' not in get_data: raise OneLogin_Saml2_ValidationError( 'The Message of the Logout Request is not signed and the SP require it', OneLogin_Saml2_ValidationError.NO_SIGNED_MESSAGE) if 'Signature' in get_data: if 'SigAlg' not in get_data: sign_alg = OneLogin_Saml2_Constants.RSA_SHA1 else: sign_alg = get_data['SigAlg'] signed_query = 'SAMLRequest=%s' % OneLogin_Saml2_Utils.get_encoded_parameter( get_data, 'SAMLRequest', lowercase_urlencoding=lowercase_urlencoding) if 'RelayState' in get_data: signed_query = '%s&RelayState=%s' % ( signed_query, OneLogin_Saml2_Utils.get_encoded_parameter( get_data, 'RelayState', lowercase_urlencoding=lowercase_urlencoding)) signed_query = '%s&SigAlg=%s' % ( signed_query, OneLogin_Saml2_Utils.get_encoded_parameter( get_data, 'SigAlg', OneLogin_Saml2_Constants.RSA_SHA1, lowercase_urlencoding=lowercase_urlencoding)) exists_x509cert = 'x509cert' in idp_data and idp_data[ 'x509cert'] exists_multix509sign = 'x509certMulti' in idp_data and \ 'signing' in idp_data['x509certMulti'] and \ idp_data['x509certMulti']['signing'] if not (exists_x509cert or exists_multix509sign): raise OneLogin_Saml2_Error( 'In order to validate the sign on the Logout Request, the x509cert of the IdP is required', OneLogin_Saml2_Error.CERT_NOT_FOUND) if exists_multix509sign: for cert in idp_data['x509certMulti']['signing']: if OneLogin_Saml2_Utils.validate_binary_sign( signed_query, b64decode(get_data['Signature']), cert, sign_alg): return True raise OneLogin_Saml2_ValidationError( 'Signature validation failed. Logout Request rejected', OneLogin_Saml2_ValidationError.INVALID_SIGNATURE) else: cert = idp_data['x509cert'] if not OneLogin_Saml2_Utils.validate_binary_sign( signed_query, b64decode(get_data['Signature']), cert, sign_alg): raise OneLogin_Saml2_ValidationError( 'Signature validation failed. Logout Request rejected', OneLogin_Saml2_ValidationError.INVALID_SIGNATURE) return True except Exception as err: # pylint: disable=R0801sign_alg self.__error = err.__str__() debug = self.__settings.is_debug_active() if debug: print(err.__str__()) if raise_exceptions: raise err return False
def is_valid(self, request_data, request_id=None): """ Determines if the SAML LogoutResponse is valid :param request_id: The ID of the LogoutRequest sent by this SP to the IdP :type request_id: string :return: Returns if the SAML LogoutResponse is or not valid :rtype: boolean """ self.__error = None lowercase_urlencoding = False try: idp_data = self.__settings.get_idp_data() idp_entity_id = idp_data['entityId'] get_data = request_data['get_data'] if 'lowercase_urlencoding' in request_data.keys(): lowercase_urlencoding = request_data['lowercase_urlencoding'] if self.__settings.is_strict(): res = OneLogin_Saml2_Utils.validate_xml(self.document, 'saml-schema-protocol-2.0.xsd', self.__settings.is_debug_active()) if not isinstance(res, Document): raise Exception('Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd') security = self.__settings.get_security_data() # Check if the InResponseTo of the Logout Response matchs the ID of the Logout Request (requestId) if provided if request_id is not None and self.document.documentElement.hasAttribute('InResponseTo'): in_response_to = self.document.documentElement.getAttribute('InResponseTo') if request_id != in_response_to: raise Exception('The InResponseTo of the Logout Response: %s, does not match the ID of the Logout request sent by the SP: %s' % (in_response_to, request_id)) # Check issuer issuer = self.get_issuer() if issuer is not None and issuer != idp_entity_id: raise Exception('Invalid issuer in the Logout Request') current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data) # Check destination if self.document.documentElement.hasAttribute('Destination'): destination = self.document.documentElement.getAttribute('Destination') if destination != '': if current_url not in destination: raise Exception('The LogoutRequest was received at $currentURL instead of $destination') if security['wantMessagesSigned']: if 'Signature' not in get_data: raise Exception('The Message of the Logout Response is not signed and the SP require it') if 'Signature' in get_data: if 'SigAlg' not in get_data: sign_alg = OneLogin_Saml2_Constants.RSA_SHA1 else: sign_alg = get_data['SigAlg'] signed_query = 'SAMLResponse=%s' % OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'SAMLResponse', lowercase_urlencoding=lowercase_urlencoding) if 'RelayState' in get_data: signed_query = '%s&RelayState=%s' % (signed_query, OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'RelayState', lowercase_urlencoding=lowercase_urlencoding)) signed_query = '%s&SigAlg=%s' % (signed_query, OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'SigAlg', OneLogin_Saml2_Constants.RSA_SHA1, lowercase_urlencoding=lowercase_urlencoding)) if 'x509cert' not in idp_data or idp_data['x509cert'] is None: raise Exception('In order to validate the sign on the Logout Response, the x509cert of the IdP is required') cert = idp_data['x509cert'] if not OneLogin_Saml2_Utils.validate_binary_sign(signed_query, b64decode(get_data['Signature']), cert, sign_alg): raise Exception('Signature validation failed. Logout Response rejected') return True # pylint: disable=R0801 except Exception as err: self.__error = err.__str__() debug = self.__settings.is_debug_active() if debug: print err.__str__() return False
def is_valid(self, request_data): """ Checks if the Logout Request received is valid :param request_data: Request Data :type request_data: dict :return: If the Logout Request is or not valid :rtype: boolean """ self.__error = None lowercase_urlencoding = False try: dom = fromstring(self.__logout_request) idp_data = self.__settings.get_idp_data() idp_entity_id = idp_data['entityId'] if 'get_data' in request_data.keys(): get_data = request_data['get_data'] else: get_data = {} if 'lowercase_urlencoding' in request_data.keys(): lowercase_urlencoding = request_data['lowercase_urlencoding'] if self.__settings.is_strict(): res = OneLogin_Saml2_Utils.validate_xml( dom, 'saml-schema-protocol-2.0.xsd', self.__settings.is_debug_active()) if not isinstance(res, Document): raise Exception( 'Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd' ) security = self.__settings.get_security_data() current_url = OneLogin_Saml2_Utils.get_self_url_no_query( request_data) # Check NotOnOrAfter if dom.get('NotOnOrAfter', None): na = OneLogin_Saml2_Utils.parse_SAML_to_time( dom.get('NotOnOrAfter')) if na <= OneLogin_Saml2_Utils.now(): raise Exception( 'Timing issues (please check your clock settings)') # Check destination if dom.get('Destination', None): destination = dom.get('Destination') if destination != '': if current_url not in destination: raise Exception( 'The LogoutRequest was received at ' '%(currentURL)s instead of %(destination)s' % { 'currentURL': current_url, 'destination': destination, }) # Check issuer issuer = OneLogin_Saml2_Logout_Request.get_issuer(dom) if issuer is not None and issuer != idp_entity_id: raise Exception('Invalid issuer in the Logout Request') if security['wantMessagesSigned']: if 'Signature' not in get_data: raise Exception( 'The Message of the Logout Request is not signed and the SP require it' ) if 'Signature' in get_data: if 'SigAlg' not in get_data: sign_alg = OneLogin_Saml2_Constants.RSA_SHA1 else: sign_alg = get_data['SigAlg'] signed_query = 'SAMLRequest=%s' % OneLogin_Saml2_Utils.get_encoded_parameter( get_data, 'SAMLRequest', lowercase_urlencoding=lowercase_urlencoding) if 'RelayState' in get_data: signed_query = '%s&RelayState=%s' % ( signed_query, OneLogin_Saml2_Utils.get_encoded_parameter( get_data, 'RelayState', lowercase_urlencoding=lowercase_urlencoding)) signed_query = '%s&SigAlg=%s' % ( signed_query, OneLogin_Saml2_Utils.get_encoded_parameter( get_data, 'SigAlg', OneLogin_Saml2_Constants.RSA_SHA1, lowercase_urlencoding=lowercase_urlencoding)) if 'x509cert' not in idp_data or idp_data['x509cert'] is None: raise Exception( 'In order to validate the sign on the Logout Request, the x509cert of the IdP is required' ) cert = idp_data['x509cert'] if not OneLogin_Saml2_Utils.validate_binary_sign( signed_query, b64decode(get_data['Signature']), cert, sign_alg): raise Exception( 'Signature validation failed. Logout Request rejected') return True except Exception as err: # pylint: disable=R0801sign_alg self.__error = err.__str__() debug = self.__settings.is_debug_active() if debug: print err.__str__() return False
def is_valid(self, request_data, raise_exceptions=False): """ Checks if the Logout Request received is valid :param request_data: Request Data :type request_data: dict :param raise_exceptions: Whether to return false on failure or raise an exception :type raise_exceptions: Boolean :return: If the Logout Request is or not valid :rtype: boolean """ self.__error = None lowercase_urlencoding = False try: dom = fromstring(self.__logout_request, forbid_dtd=True) idp_data = self.__settings.get_idp_data() idp_entity_id = idp_data['entityId'] if 'get_data' in request_data.keys(): get_data = request_data['get_data'] else: get_data = {} if 'lowercase_urlencoding' in request_data.keys(): lowercase_urlencoding = request_data['lowercase_urlencoding'] if self.__settings.is_strict(): res = OneLogin_Saml2_Utils.validate_xml(dom, 'saml-schema-protocol-2.0.xsd', self.__settings.is_debug_active()) if not isinstance(res, Document): raise OneLogin_Saml2_ValidationError( 'Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd', OneLogin_Saml2_ValidationError.INVALID_XML_FORMAT ) security = self.__settings.get_security_data() current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data) # Check NotOnOrAfter if dom.get('NotOnOrAfter', None): na = OneLogin_Saml2_Utils.parse_SAML_to_time(dom.get('NotOnOrAfter')) if na <= OneLogin_Saml2_Utils.now(): raise OneLogin_Saml2_ValidationError( 'Could not validate timestamp: expired. Check system clock.', OneLogin_Saml2_ValidationError.RESPONSE_EXPIRED ) # Check destination if dom.get('Destination', None): destination = dom.get('Destination') if destination != '': if current_url not in destination: raise Exception( 'The LogoutRequest was received at ' '%(currentURL)s instead of %(destination)s' % { 'currentURL': current_url, 'destination': destination, }, OneLogin_Saml2_ValidationError.WRONG_DESTINATION ) # Check issuer issuer = OneLogin_Saml2_Logout_Request.get_issuer(dom) if issuer is not None and issuer != idp_entity_id: raise OneLogin_Saml2_ValidationError( 'Invalid issuer in the Logout Request (expected %(idpEntityId)s, got %(issuer)s)' % { 'idpEntityId': idp_entity_id, 'issuer': issuer }, OneLogin_Saml2_ValidationError.WRONG_ISSUER ) if security['wantMessagesSigned']: if 'Signature' not in get_data: raise OneLogin_Saml2_ValidationError( 'The Message of the Logout Request is not signed and the SP require it', OneLogin_Saml2_ValidationError.NO_SIGNED_MESSAGE ) if 'Signature' in get_data: if 'SigAlg' not in get_data: sign_alg = OneLogin_Saml2_Constants.RSA_SHA1 else: sign_alg = get_data['SigAlg'] signed_query = 'SAMLRequest=%s' % OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'SAMLRequest', lowercase_urlencoding=lowercase_urlencoding) if 'RelayState' in get_data: signed_query = '%s&RelayState=%s' % (signed_query, OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'RelayState', lowercase_urlencoding=lowercase_urlencoding)) signed_query = '%s&SigAlg=%s' % (signed_query, OneLogin_Saml2_Utils.get_encoded_parameter(get_data, 'SigAlg', OneLogin_Saml2_Constants.RSA_SHA1, lowercase_urlencoding=lowercase_urlencoding)) exists_x509cert = 'x509cert' in idp_data and idp_data['x509cert'] exists_multix509sign = 'x509certMulti' in idp_data and \ 'signing' in idp_data['x509certMulti'] and \ idp_data['x509certMulti']['signing'] if not (exists_x509cert or exists_multix509sign): raise OneLogin_Saml2_Error( 'In order to validate the sign on the Logout Request, the x509cert of the IdP is required', OneLogin_Saml2_Error.CERT_NOT_FOUND ) if exists_multix509sign: for cert in idp_data['x509certMulti']['signing']: if OneLogin_Saml2_Utils.validate_binary_sign(signed_query, b64decode(get_data['Signature']), cert, sign_alg): return True raise OneLogin_Saml2_ValidationError( 'Signature validation failed. Logout Request rejected', OneLogin_Saml2_ValidationError.INVALID_SIGNATURE ) else: cert = idp_data['x509cert'] if not OneLogin_Saml2_Utils.validate_binary_sign(signed_query, b64decode(get_data['Signature']), cert, sign_alg): raise OneLogin_Saml2_ValidationError( 'Signature validation failed. Logout Request rejected', OneLogin_Saml2_ValidationError.INVALID_SIGNATURE ) return True except Exception as err: # pylint: disable=R0801sign_alg self.__error = err.__str__() debug = self.__settings.is_debug_active() if debug: print(err.__str__()) if raise_exceptions: raise err return False