Example #1
0
    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"')
Example #2
0
    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())
Example #7
0
    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)
Example #10
0
    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)
Example #12
0
    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'])
Example #16
0
    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
Example #17
0
    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')
Example #19
0
    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(),
        }
Example #20
0
    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'))
Example #22
0
    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)
Example #23
0
    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)
Example #24
0
    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))
Example #25
0
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
Example #26
0
    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')
Example #28
0
    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)
Example #29
0
    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())