def testCreateEncSAMLRequest(self): """ Tests the OneLogin_Saml2_Authn_Request Constructor. The creation of a deflated SAML Request """ settings = self.loadSettingsJSON() settings['organization'] = { 'es': { 'name': 'sp_prueba', 'displayname': 'SP prueba', 'url': 'http://sp.example.com' } } settings['security']['wantNameIdEncrypted'] = True settings = OneLogin_Saml2_Settings(settings) authn_request = OneLogin_Saml2_Authn_Request(settings) parameters = {'SAMLRequest': authn_request.get_request()} auth_url = OneLogin_Saml2_Utils.redirect( 'http://idp.example.com/SSOService.php', parameters, True) self.assertRegex( auth_url, '^http://idp\.example\.com\/SSOService\.php\?SAMLRequest=') exploded = urlparse(auth_url) exploded = parse_qs(exploded[4]) payload = exploded['SAMLRequest'][0] inflated = compat.to_string( OneLogin_Saml2_Utils.decode_base64_and_inflate(payload)) self.assertRegex(inflated, '^<samlp:AuthnRequest') self.assertRegex( inflated, 'AssertionConsumerServiceURL="http://stuff.com/endpoints/endpoints/acs.php">' ) self.assertRegex( inflated, '<saml:Issuer>http://stuff.com/endpoints/metadata.php</saml:Issuer>' ) self.assertRegex( inflated, 'Format="urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted"') self.assertRegex(inflated, 'ProviderName="SP prueba"')
def testBuilderAttributeConsumingService(self): settings = OneLogin_Saml2_Settings(self.loadSettingsJSON('settings4.json')) sp_data = settings.get_sp_data() security = settings.get_security_data() organization = settings.get_organization() contacts = settings.get_contacts() metadata = OneLogin_Saml2_Metadata.builder( sp_data, security['authnRequestsSigned'], security['wantAssertionsSigned'], None, None, contacts, organization ) self.assertIn(""" <md:AttributeConsumingService index="1"> <md:ServiceName xml:lang="en">Test Service</md:ServiceName> <md:ServiceDescription xml:lang="en">Test Service</md:ServiceDescription> <md:RequestedAttribute Name="urn:oid:2.5.4.42" FriendlyName="givenName" /> <md:RequestedAttribute Name="urn:oid:2.5.4.4" FriendlyName="sn" /> <md:RequestedAttribute Name="urn:oid:2.16.840.1.113730.3.1.241" FriendlyName="displayName" /> <md:RequestedAttribute Name="urn:oid:0.9.2342.19200300.100.1.3" FriendlyName="mail" /> <md:RequestedAttribute Name="urn:oid:0.9.2342.19200300.100.1.1" FriendlyName="uid" /> </md:AttributeConsumingService>""", metadata)
def testGetXML(self): """ Tests that we can get the logout request XML directly without going through intermediate steps """ request = self.file_contents( join(self.data_path, 'logout_requests', 'logout_request.xml')) settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) logout_request_generated = OneLogin_Saml2_Logout_Request(settings) expectedFragment = ( 'Destination="http://idp.example.com/SingleLogoutService.php">\n' ' <saml:Issuer>http://stuff.com/endpoints/metadata.php</saml:Issuer>\n' ' <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">http://idp.example.com/</saml:NameID>\n' ' \n </samlp:LogoutRequest>') self.assertIn(expectedFragment, logout_request_generated.get_xml()) logout_request_processed = OneLogin_Saml2_Logout_Request( settings, b64encode(request)) self.assertEqual(request, logout_request_processed.get_xml())
def testCreateDeflatedSAMLLogoutRequestURLParameter(self): """ Tests the OneLogin_Saml2_LogoutRequest Constructor. The creation of a deflated SAML Logout Request """ settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) logout_request = OneLogin_Saml2_Logout_Request(settings) parameters = {'SAMLRequest': logout_request.get_request()} logout_url = OneLogin_Saml2_Utils.redirect( 'http://idp.example.com/SingleLogoutService.php', parameters, True) self.assertRegex( logout_url, '^http://idp\.example\.com\/SingleLogoutService\.php\?SAMLRequest=' ) url_parts = urlparse(logout_url) exploded = parse_qs(url_parts.query) payload = exploded['SAMLRequest'][0] inflated = compat.to_string( OneLogin_Saml2_Utils.decode_base64_and_inflate(payload)) self.assertRegex(inflated, '^<samlp:LogoutRequest')
def testIsInvalidNotOnOrAfter(self): """ Tests the is_valid method of the OneLogin_Saml2_LogoutRequest Case Invalid NotOnOrAfter """ request_data = { 'http_host': 'example.com', 'script_name': 'index.html' } request = self.file_contents(join(self.data_path, 'logout_requests', 'invalids', 'not_after_failed.xml')) current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data) request = request.replace('http://stuff.com/endpoints/endpoints/sls.php', current_url) settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) self.assertTrue(OneLogin_Saml2_Logout_Request.is_valid(settings, request, request_data)) settings.set_strict(True) try: valid = OneLogin_Saml2_Logout_Request.is_valid(settings, request, request_data) self.assertFalse(valid) except Exception as e: self.assertIn('Timing issues (please check your clock settings)', e.message)
def testIsInvalidNotOnOrAfter(self): """ Tests the is_valid method of the OneLogin_Saml2_LogoutRequest Case Invalid NotOnOrAfter """ request_data = { 'http_host': 'example.com', 'script_name': 'index.html' } request = self.file_contents(join(self.data_path, 'logout_requests', 'invalids', 'not_after_failed.xml')) current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data) request = request.replace('http://stuff.com/endpoints/endpoints/sls.php', current_url) settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) logout_request = OneLogin_Saml2_Logout_Request(settings, b64encode(request)) self.assertTrue(logout_request.is_valid(request_data)) settings.set_strict(True) logout_request2 = OneLogin_Saml2_Logout_Request(settings, b64encode(request)) self.assertFalse(logout_request2.is_valid(request_data)) self.assertIn('Could not validate timestamp: expired. Check system clock.', logout_request2.get_error())
def testBuilderAttributeConsumingServiceWithMultipleAttributeValue(self): settings = OneLogin_Saml2_Settings(self.loadSettingsJSON('settings5.json')) sp_data = settings.get_sp_data() security = settings.get_security_data() organization = settings.get_organization() contacts = settings.get_contacts() metadata = OneLogin_Saml2_Metadata.builder( sp_data, security['authnRequestsSigned'], security['wantAssertionsSigned'], None, None, contacts, organization ) self.assertIn(""" <md:AttributeConsumingService index="1"> <md:ServiceName xml:lang="en">Test Service</md:ServiceName> <md:ServiceDescription xml:lang="en">Test Service</md:ServiceDescription> <md:RequestedAttribute Name="userType" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:basic"> <saml:AttributeValue xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">userType</saml:AttributeValue> <saml:AttributeValue xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">admin</saml:AttributeValue> </md:RequestedAttribute> <md:RequestedAttribute Name="urn:oid:0.9.2342.19200300.100.1.1" FriendlyName="uid" /> </md:AttributeConsumingService>""", metadata)
def testIsInValidDestination(self): """ Tests the is_valid method of the OneLogin_Saml2_LogoutResponse Case invalid Destination """ request_data = { 'http_host': 'example.com', 'script_name': 'index.html', 'get_data': {} } settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) message = self.file_contents( join(self.data_path, 'logout_responses', 'logout_response_deflated.xml.base64')) settings.set_strict(False) response = OneLogin_Saml2_Logout_Response(settings, message) self.assertTrue(response.is_valid(request_data)) settings.set_strict(True) response_2 = OneLogin_Saml2_Logout_Response(settings, message) self.assertFalse(response_2.is_valid(request_data)) self.assertIn('The LogoutResponse was received at', response_2.get_error()) # Empty destination dom = parseString( OneLogin_Saml2_Utils.decode_base64_and_inflate(message)) dom.firstChild.setAttribute('Destination', '') xml = dom.toxml() message_3 = OneLogin_Saml2_Utils.deflate_and_base64_encode(xml) response_3 = OneLogin_Saml2_Logout_Response(settings, message_3) self.assertTrue(response_3.is_valid(request_data)) # No destination dom.firstChild.removeAttribute('Destination') xml = dom.toxml() message_4 = OneLogin_Saml2_Utils.deflate_and_base64_encode(xml) response_4 = OneLogin_Saml2_Logout_Response(settings, message_4) self.assertTrue(response_4.is_valid(request_data))
def testGetNameId(self): """ Tests the get_nameid of the OneLogin_Saml2_LogoutRequest """ request = self.file_contents( join(self.data_path, 'logout_requests', 'logout_request.xml')) name_id = OneLogin_Saml2_Logout_Request.get_nameid(request) self.assertEqual(name_id, 'ONELOGIN_1e442c129e1f822c8096086a1103c5ee2c7cae1c') request_2 = self.file_contents( join(self.data_path, 'logout_requests', 'logout_request_encrypted_nameid.xml')) with self.assertRaisesRegexp( Exception, 'Key is required in order to decrypt the NameID'): OneLogin_Saml2_Logout_Request.get_nameid(request_2) settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) key = settings.get_sp_key() name_id_3 = OneLogin_Saml2_Logout_Request.get_nameid(request_2, key) self.assertEqual('ONELOGIN_9c86c4542ab9d6fce07f2f7fd335287b9b3cdf69', name_id_3)
def testAddX509KeyDescriptors(self): """ Tests the addX509KeyDescriptors method of the OneLogin_Saml2_Metadata """ settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) sp_data = settings.get_sp_data() metadata = OneLogin_Saml2_Metadata.builder(sp_data) self.assertNotIn('<md:KeyDescriptor use="signing"', metadata) self.assertNotIn('<md:KeyDescriptor use="encryption"', metadata) metadata_without_descriptors = OneLogin_Saml2_Metadata.add_x509_key_descriptors(metadata, None) self.assertNotIn('<md:KeyDescriptor use="signing"', metadata_without_descriptors) self.assertNotIn('<md:KeyDescriptor use="encryption"', metadata_without_descriptors) metadata_without_descriptors = OneLogin_Saml2_Metadata.add_x509_key_descriptors(metadata, '') self.assertNotIn('<md:KeyDescriptor use="signing"', metadata_without_descriptors) self.assertNotIn('<md:KeyDescriptor use="encryption"', metadata_without_descriptors) cert_path = settings.get_cert_path() cert = self.file_contents(join(cert_path, 'sp.crt')) metadata_with_descriptors = OneLogin_Saml2_Metadata.add_x509_key_descriptors(metadata, cert) self.assertIn('<md:KeyDescriptor use="signing"', metadata_with_descriptors) self.assertIn('<md:KeyDescriptor use="encryption"', metadata_with_descriptors) try: OneLogin_Saml2_Metadata.add_x509_key_descriptors('', cert) self.assertTrue(False) except Exception as e: self.assertIn('Error parsing metadata', e.message) base_path = dirname(dirname(dirname(dirname(__file__)))) unparsed_metadata = self.file_contents(join(base_path, 'data', 'metadata', 'unparsed_metadata.xml')) try: metadata_with_descriptors = OneLogin_Saml2_Metadata.add_x509_key_descriptors(unparsed_metadata, cert) self.assertFalse(True) except Exception as e: self.assertIn('Error parsing metadata', e.message)
def testGetIssuer(self): """ Tests the get_issuer of the OneLogin_Saml2_LogoutResponse """ settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) message = self.file_contents( join(self.data_path, 'logout_responses', 'logout_response_deflated.xml.base64')) response = OneLogin_Saml2_Logout_Response(settings, message) issuer = response.get_issuer() self.assertEquals('http://idp.example.com/', issuer) dom = parseString( OneLogin_Saml2_Utils.decode_base64_and_inflate(message)) issuer_node = dom.getElementsByTagName('saml:Issuer')[0] issuer_node.parentNode.removeChild(issuer_node) xml = dom.toxml() message_2 = OneLogin_Saml2_Utils.deflate_and_base64_encode(xml) response_2 = OneLogin_Saml2_Logout_Response(settings, message_2) issuer_2 = response_2.get_issuer() self.assertIsNone(issuer_2)
def testIsInValidWithCapitalization(self): """ Tests the is_valid method of the OneLogin_Saml2_LogoutRequest """ request_data = { 'http_host': 'example.com', 'script_name': 'INdex.html' } request = self.file_contents( join(self.data_path, 'logout_requests', 'logout_request.xml')) settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) logout_request = OneLogin_Saml2_Logout_Request(settings, b64encode(request)) self.assertTrue(logout_request.is_valid(request_data)) settings.set_strict(True) logout_request2 = OneLogin_Saml2_Logout_Request( settings, b64encode(request)) self.assertFalse(logout_request2.is_valid(request_data)) settings.set_strict(False) dom = parseString(request) logout_request3 = OneLogin_Saml2_Logout_Request( settings, b64encode(dom.toxml())) self.assertTrue(logout_request3.is_valid(request_data)) settings.set_strict(True) logout_request4 = OneLogin_Saml2_Logout_Request( settings, b64encode(dom.toxml())) self.assertFalse(logout_request4.is_valid(request_data)) current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data) request = request.replace( 'http://stuff.com/endpoints/endpoints/sls.php', current_url.lower()) logout_request5 = OneLogin_Saml2_Logout_Request( settings, b64encode(request)) self.assertFalse(logout_request5.is_valid(request_data))
def testBuildWithStatus(self): """ Tests the build method when called specifying a non-default status for the LogoutResponse. """ settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) response_builder = OneLogin_Saml2_Logout_Response(settings) response_builder.build( "InResponseValue", status=OneLogin_Saml2_Constants.STATUS_REQUESTER) generated_encoded_response = response_builder.get_response() # Parse and verify the status of the response, as the receiver will do: parsed_response = OneLogin_Saml2_Logout_Response( settings, generated_encoded_response) expectedFragment = ( ' <samlp:Status>\n' ' <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Requester" />\n' ' </samlp:Status>\n') self.assertIn(expectedFragment, parsed_response.get_xml()) self.assertEqual(parsed_response.get_status(), OneLogin_Saml2_Constants.STATUS_REQUESTER)
def testGetIdPData(self): """ Tests the getIdPData method of the OneLogin_Saml2_Settings """ settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) idp_data = settings.get_idp_data() self.assertNotEqual(len(idp_data), 0) self.assertIn('entityId', idp_data) self.assertIn('singleSignOnService', idp_data) self.assertIn('singleLogoutService', idp_data) self.assertIn('x509cert', idp_data) self.assertEqual('http://idp.example.com/', idp_data['entityId']) self.assertEqual('http://idp.example.com/SSOService.php', idp_data['singleSignOnService']['url']) self.assertEqual('http://idp.example.com/SingleLogoutService.php', idp_data['singleLogoutService']['url']) x509cert = 'MIICgTCCAeoCCQCbOlrWDdX7FTANBgkqhkiG9w0BAQUFADCBhDELMAkGA1UEBhMCTk8xGDAWBgNVBAgTD0FuZHJlYXMgU29sYmVyZzEMMAoGA1UEBxMDRm9vMRAwDgYDVQQKEwdVTklORVRUMRgwFgYDVQQDEw9mZWlkZS5lcmxhbmcubm8xITAfBgkqhkiG9w0BCQEWEmFuZHJlYXNAdW5pbmV0dC5ubzAeFw0wNzA2MTUxMjAxMzVaFw0wNzA4MTQxMjAxMzVaMIGEMQswCQYDVQQGEwJOTzEYMBYGA1UECBMPQW5kcmVhcyBTb2xiZXJnMQwwCgYDVQQHEwNGb28xEDAOBgNVBAoTB1VOSU5FVFQxGDAWBgNVBAMTD2ZlaWRlLmVybGFuZy5ubzEhMB8GCSqGSIb3DQEJARYSYW5kcmVhc0B1bmluZXR0Lm5vMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDivbhR7P516x/S3BqKxupQe0LONoliupiBOesCO3SHbDrl3+q9IbfnfmE04rNuMcPsIxB161TdDpIesLCn7c8aPHISKOtPlAeTZSnb8QAu7aRjZq3+PbrP5uW3TcfCGPtKTytHOge/OlJbo078dVhXQ14d1EDwXJW1rRXuUt4C8QIDAQABMA0GCSqGSIb3DQEBBQUAA4GBACDVfp86HObqY+e8BUoWQ9+VMQx1ASDohBjwOsg2WykUqRXF+dLfcUH9dWR63CtZIKFDbStNomPnQz7nbK+onygwBspVEbnHuUihZq3ZUdmumQqCw4Uvs/1Uvq3orOo/WJVhTyvLgFVK2QarQ4/67OZfHd7R+POBXhophSMv1ZOo' formated_x509_cert = OneLogin_Saml2_Utils.format_cert(x509cert) self.assertEqual(formated_x509_cert, idp_data['x509cert'])
def testGetSPData(self): """ Tests the getSPData method of the OneLogin_Saml2_Settings """ settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) sp_data = settings.get_sp_data() self.assertNotEqual(len(sp_data), 0) self.assertIn('entityId', sp_data) self.assertIn('assertionConsumerService', sp_data) self.assertIn('singleLogoutService', sp_data) self.assertIn('NameIDFormat', sp_data) self.assertEqual('http://stuff.com/endpoints/metadata.php', sp_data['entityId']) self.assertEqual('http://stuff.com/endpoints/endpoints/acs.php', sp_data['assertionConsumerService']['url']) self.assertEqual('http://stuff.com/endpoints/endpoints/sls.php', sp_data['singleLogoutService']['url']) self.assertEqual( 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified', sp_data['NameIDFormat'])
def __init__(self, request_data, old_settings=None, custom_base_path=None): """ Initializes the SP SAML instance. :param request_data: Request Data :type request_data: dict :param settings: Optional. SAML Toolkit Settings :type settings: dict|object :param custom_base_path: Optional. Path where are stored the settings file and the cert folder :type custom_base_path: string """ self.__request_data = request_data self.__settings = OneLogin_Saml2_Settings(old_settings, custom_base_path) self.__attributes = [] self.__nameid = None self.__session_index = None self.__authenticated = False self.__errors = [] self.__error_reason = None
def __init__(self, request_data, old_settings=None, custom_base_path=None): """ Initializes the SP SAML instance. :param request_data: Request Data :type request_data: dict :param old_settings: Optional. SAML Toolkit Settings :type old_settings: dict :param custom_base_path: Optional. Path where are stored the settings file and the cert folder :type custom_base_path: string """ self._request_data = request_data if isinstance(old_settings, OneLogin_Saml2_Settings): self._settings = old_settings else: self._settings = OneLogin_Saml2_Settings(old_settings, custom_base_path) self._attributes = dict() self._friendlyname_attributes = dict() self._nameid = None self._nameid_format = None self._nameid_nq = None self._nameid_spnq = None self._session_index = None self._session_expiration = None self._authenticated = False self._errors = [] self._error_reason = None self._last_request_id = None self._last_message_id = None self._last_assertion_id = None self._last_assertion_issue_instant = None self._last_authn_contexts = [] self._last_request = None self._last_response = None self._last_response_in_response_to = None self._last_assertion_not_on_or_after = None
def testConstructor(self): """ Tests the OneLogin_Saml2_LogoutRequest Constructor. """ settings_info = self.loadSettingsJSON() settings_info['security']['nameIdEncrypted'] = True settings = OneLogin_Saml2_Settings(settings_info) logout_request = OneLogin_Saml2_Logout_Request(settings) parameters = {'SAMLRequest': logout_request.get_request()} logout_url = OneLogin_Saml2_Utils.redirect( 'http://idp.example.com/SingleLogoutService.php', parameters, True) self.assertRegexpMatches( logout_url, '^http://idp\.example\.com\/SingleLogoutService\.php\?SAMLRequest=' ) url_parts = urlparse(logout_url) exploded = parse_qs(url_parts.query) payload = exploded['SAMLRequest'][0] inflated = OneLogin_Saml2_Utils.decode_base64_and_inflate(payload) self.assertRegexpMatches(inflated, '^<samlp:LogoutRequest')
def get_settings(self, db, idp_entity_id): """Returns a dictionary containing SP's and IdP's settings in the OneLogin's SAML Toolkit format :param db: Database session :type db: sqlalchemy.orm.session.Session :param idp_entity_id: IdP's entity ID :type idp_entity_id: string :return: Dictionary containing SP's and IdP's settings in the OneLogin's SAML Toolkit format :rtype: Dict """ onelogin_settings = { self.DEBUG: self._configuration.service_provider_debug_mode, self.STRICT: self._configuration.service_provider_strict_mode, } identity_provider_settings = self.get_identity_provider_settings( db, idp_entity_id ) service_provider_settings = self.get_service_provider_settings(db) onelogin_settings.update(identity_provider_settings) onelogin_settings.update(service_provider_settings) # We need to use disjunction separately because dict.update just overwrites values onelogin_settings[self.SECURITY][self.AUTHN_REQUESTS_SIGNED] = ( service_provider_settings[self.SECURITY][self.AUTHN_REQUESTS_SIGNED] or service_provider_settings[self.SECURITY][self.AUTHN_REQUESTS_SIGNED] ) settings = OneLogin_Saml2_Settings(onelogin_settings) return { self.DEBUG: self._configuration.service_provider_debug_mode, self.STRICT: self._configuration.service_provider_strict_mode, self.IDP: settings.get_idp_data(), self.SP: settings.get_sp_data(), self.SECURITY: settings.get_security_data(), }
def testAddX509KeyDescriptors(self): """ Tests the addX509KeyDescriptors method of the OneLogin_Saml2_Metadata """ settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) sp_data = settings.get_sp_data() metadata = OneLogin_Saml2_Metadata.builder(sp_data) self.assertNotIn('<md:KeyDescriptor use="signing"', metadata) self.assertNotIn('<md:KeyDescriptor use="encryption"', metadata) metadata_without_descriptors = OneLogin_Saml2_Metadata.add_x509_key_descriptors(metadata, None) self.assertNotIn('<md:KeyDescriptor use="signing"', metadata_without_descriptors) self.assertNotIn('<md:KeyDescriptor use="encryption"', metadata_without_descriptors) metadata_without_descriptors = OneLogin_Saml2_Metadata.add_x509_key_descriptors(metadata, '') self.assertNotIn('<md:KeyDescriptor use="signing"', metadata_without_descriptors) self.assertNotIn('<md:KeyDescriptor use="encryption"', metadata_without_descriptors) cert_path = settings.get_cert_path() cert = self.file_contents(join(cert_path, 'sp.crt')) metadata_with_descriptors = compat.to_string(OneLogin_Saml2_Metadata.add_x509_key_descriptors(metadata, cert)) self.assertIn('<md:KeyDescriptor use="signing"', metadata_with_descriptors) self.assertIn('<md:KeyDescriptor use="encryption"', metadata_with_descriptors) with self.assertRaises(Exception) as context: OneLogin_Saml2_Metadata.add_x509_key_descriptors('', cert) exception = context.exception self.assertIn("Error parsing metadata", str(exception)) base_path = dirname(dirname(dirname(dirname(__file__)))) unparsed_metadata = self.file_contents(join(base_path, 'data', 'metadata', 'unparsed_metadata.xml')) with self.assertRaises(Exception) as context: OneLogin_Saml2_Metadata.add_x509_key_descriptors(unparsed_metadata, cert) exception = context.exception self.assertIn("Error parsing metadata", str(exception))
def testGetDefaultSecurityValues(self): """ Tests default values of Security advanced sesettings """ settings_json = self.loadSettingsJSON() del settings_json['security'] settings = OneLogin_Saml2_Settings(settings_json) security = settings.get_security_data() self.assertIn('nameIdEncrypted', security) self.assertFalse(security.get('nameIdEncrypted')) self.assertIn('authnRequestsSigned', security) self.assertFalse(security.get('authnRequestsSigned')) self.assertIn('logoutRequestSigned', security) self.assertFalse(security.get('logoutRequestSigned')) self.assertIn('logoutResponseSigned', security) self.assertFalse(security.get('logoutResponseSigned')) self.assertIn('signMetadata', security) self.assertFalse(security.get('signMetadata')) self.assertIn('wantMessagesSigned', security) self.assertFalse(security.get('wantMessagesSigned')) self.assertIn('wantAssertionsSigned', security) self.assertFalse(security.get('wantAssertionsSigned')) self.assertIn('requestedAuthnContext', security) self.assertTrue(security.get('requestedAuthnContext')) self.assertIn('wantNameId', security) self.assertTrue(security.get('wantNameId')) self.assertIn('wantNameIdEncrypted', security) self.assertFalse(security.get('wantNameIdEncrypted'))
def testIsInValidRequestId(self): """ Tests the is_valid method of the OneLogin_Saml2_LogoutResponse Case invalid request Id """ request_data = { 'http_host': 'example.com', 'script_name': 'index.html', 'get_data': {} } settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) message = self.file_contents( join(self.data_path, 'logout_responses', 'logout_response_deflated.xml.base64')) plain_message = compat.to_string( OneLogin_Saml2_Utils.decode_base64_and_inflate(message)) current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data) plain_message = plain_message.replace( 'http://stuff.com/endpoints/endpoints/sls.php', current_url) message = OneLogin_Saml2_Utils.deflate_and_base64_encode(plain_message) request_id = 'invalid_request_id' settings.set_strict(False) response = OneLogin_Saml2_Logout_Response(settings, message) self.assertTrue(response.is_valid(request_data, request_id)) settings.set_strict(True) response_2 = OneLogin_Saml2_Logout_Response(settings, message) self.assertFalse(response_2.is_valid(request_data, request_id)) self.assertIn('The InResponseTo of the Logout Response:', response_2.get_error()) with self.assertRaisesRegexp( Exception, 'The InResponseTo of the Logout Response:'): response_2.is_valid(request_data, request_id, raise_exceptions=True)
def testIsInvalidIssuer(self): """ Tests the is_valid method of the OneLogin_Saml2_LogoutRequest Case Invalid Issuer """ request = self.file_contents(join(self.data_path, 'logout_requests', 'invalids', 'invalid_issuer.xml')) request_data = { 'http_host': 'example.com', 'script_name': 'index.html' } current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data) request = request.replace('http://stuff.com/endpoints/endpoints/sls.php', current_url) settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) logout_request = OneLogin_Saml2_Logout_Request(settings, b64encode(request)) self.assertTrue(logout_request.is_valid(request_data)) settings.set_strict(True) try: logout_request2 = OneLogin_Saml2_Logout_Request(settings, b64encode(request)) valid = logout_request2.is_valid(request_data) self.assertFalse(valid) except Exception as e: self.assertIn('Invalid issuer in the Logout Request', e.message)
def testMocked_time_call_in_metadata_builder(self): # called via get_sp_metadata() custom_base_path = join(dirname(dirname(dirname(dirname(__file__)))), 'settings') settings = OneLogin_Saml2_Settings(custom_base_path=custom_base_path) self.assertEqual(len(settings.get_errors()), 0) delta = 3600 * 24 * 10**6 _time = [float(time() + delta)] _log = [] def time_fn(): _time[0] += 1.0 _log.append(True) return _time[0] # Mocked with mocked_time(time_fn): metadata = settings.get_sp_metadata() self.assertEquals(1, len(_log)) errors = settings.validate_metadata(metadata) self.assertFalse(errors) self.assertEquals(3, len(_log))
def metadata(request): """ Expose SP Metadata """ params = { 'sp_validation_only': True } if settings.DEBUG: params['settings'] = None params['custom_base_path'] = settings.SAML_FOLDER else: params['settings'] = SpidConfig.get_saml_settings() saml_settings = OneLogin_Saml2_Settings( **params ) metadata = saml_settings.get_sp_metadata() errors = saml_settings.validate_metadata(metadata) if len(errors) == 0: resp = HttpResponse(content=metadata, content_type='text/xml') else: resp = HttpResponseServerError(content=', '.join(errors)) return resp
def testValidateMetadata(self): """ Tests the validateMetadata method of the OneLogin_Saml2_Settings Case valid metadata """ settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) metadata = settings.get_sp_metadata() self.assertEqual(len(settings.validate_metadata(metadata)), 0) xml = self.file_contents(join(self.data_path, 'metadata', 'metadata_settings1.xml')) self.assertEqual(len(settings.validate_metadata(xml)), 0) xml_2 = '<xml>invalid</xml>' self.assertIn('invalid_xml', settings.validate_metadata(xml_2)) xml_3 = self.file_contents(join(self.data_path, 'metadata', 'entities_metadata.xml')) self.assertIn('noEntityDescriptor_xml', settings.validate_metadata(xml_3)) xml_4 = self.file_contents(join(self.data_path, 'metadata', 'idp_metadata.xml')) self.assertIn('onlySPSSODescriptor_allowed_xml', settings.validate_metadata(xml_4)) xml_5 = self.file_contents(join(self.data_path, 'metadata', 'no_expiration_mark_metadata.xml')) self.assertEqual(len(settings.validate_metadata(xml_5)), 0)
def testCreateDeflatedSAMLLogoutResponseURLParameter(self): """ Tests the OneLogin_Saml2_LogoutResponse Constructor. The creation of a deflated SAML Logout Response """ settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) in_response_to = 'ONELOGIN_21584ccdfaca36a145ae990442dcd96bfe60151e' response_builder = OneLogin_Saml2_Logout_Response(settings) response_builder.build(in_response_to) parameters = {'SAMLResponse': response_builder.get_response()} logout_url = OneLogin_Saml2_Utils.redirect( 'http://idp.example.com/SingleLogoutService.php', parameters, True) self.assertRegexpMatches( logout_url, '^http://idp\.example\.com\/SingleLogoutService\.php\?SAMLResponse=' ) url_parts = urlparse(logout_url) exploded = parse_qs(url_parts.query) inflated = OneLogin_Saml2_Utils.decode_base64_and_inflate( exploded['SAMLResponse'][0]) self.assertRegexpMatches(inflated, '^<samlp:LogoutResponse')
def testGetSPMetadata(self): """ Tests the getSPMetadata method of the OneLogin_Saml2_Settings Case unsigned metadata """ settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) metadata = settings.get_sp_metadata() self.assertNotEqual(len(metadata), 0) self.assertIn('<md:SPSSODescriptor', metadata) self.assertIn('entityID="http://stuff.com/endpoints/metadata.php"', metadata) self.assertIn('AuthnRequestsSigned="false"', metadata) self.assertIn('WantAssertionsSigned="false"', metadata) self.assertIn( '<md:AssertionConsumerService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://stuff.com/endpoints/endpoints/acs.php" index="1"/>', metadata) self.assertIn( '<md:SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://stuff.com/endpoints/endpoints/sls.php"/>', metadata) self.assertIn( '<md:NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified</md:NameIDFormat>', metadata)
def __init__(self, request_data, old_settings=None, custom_base_path=None, settings=None): """ Initializes the SP SAML instance. :param request_data: Request Data :type request_data: dict :param settings: Optional. SAML Toolkit Settings :type settings: dict :param custom_base_path: Optional. Path where are stored the settings file and the cert folder :type custom_base_path: string """ self.__request_data = request_data # TS: New hotness: create OneLogin_Saml2_Settings once; add it using the settings argument -- never specify old_settings or custom_base_path. self.__settings = settings if settings else OneLogin_Saml2_Settings( old_settings, custom_base_path) self.__attributes = [] self.__nameid = None self.__nameid_format = None self.__session_index = None self.__session_expiration = None self.__authenticated = False self.__errors = [] self.__error_reason = None self.__last_request_id = None self.__last_message_id = None self.__last_assertion_id = None self.__last_assertion_not_on_or_after = None self.__last_request = None self.__last_response = None
def testGetXML(self): """ Tests that we can get the logout response XML directly without going through intermediate steps """ response = self.file_contents(join(self.data_path, 'logout_responses', 'logout_response.xml')) settings = OneLogin_Saml2_Settings(self.loadSettingsJSON()) logout_response_generated = OneLogin_Saml2_Logout_Response(settings) logout_response_generated.build("InResponseValue") expectedFragment = ( 'Destination="http://idp.example.com/SingleLogoutService.php"\n' ' InResponseTo="InResponseValue"\n>\n' ' <saml:Issuer>http://stuff.com/endpoints/metadata.php</saml:Issuer>\n' ' <samlp:Status>\n' ' <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />\n' ' </samlp:Status>\n' '</samlp:LogoutResponse>' ) self.assertIn(expectedFragment, logout_response_generated.get_xml()) logout_response_processed = OneLogin_Saml2_Logout_Response(settings, OneLogin_Saml2_Utils.deflate_and_base64_encode(response)) self.assertEqual(response, logout_response_processed.get_xml())