예제 #1
0
    def testLoginForceAuthN(self):
        """
        Tests the login method of the OneLogin_Saml2_Auth class
        Case Logout with no parameters. A AuthN Request is built with ForceAuthn and redirect executed
        """
        settings_info = self.loadSettingsJSON()
        return_to = u"http://example.com/returnto"
        sso_url = settings_info["idp"]["singleSignOnService"]["url"]

        auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info)
        target_url = auth.login(return_to)
        parsed_query = parse_qs(urlparse(target_url)[4])
        sso_url = settings_info["idp"]["singleSignOnService"]["url"]
        self.assertIn(sso_url, target_url)
        self.assertIn("SAMLRequest", parsed_query)
        request = OneLogin_Saml2_Utils.decode_base64_and_inflate(parsed_query["SAMLRequest"][0])
        self.assertNotIn('ForceAuthn="true"', request)

        auth_2 = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info)
        target_url_2 = auth_2.login(return_to, False, False)
        parsed_query_2 = parse_qs(urlparse(target_url_2)[4])
        self.assertIn(sso_url, target_url_2)
        self.assertIn("SAMLRequest", parsed_query_2)
        request_2 = OneLogin_Saml2_Utils.decode_base64_and_inflate(parsed_query_2["SAMLRequest"][0])
        self.assertNotIn('ForceAuthn="true"', request_2)

        auth_3 = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info)
        target_url_3 = auth_3.login(return_to, True, False)
        parsed_query_3 = parse_qs(urlparse(target_url_3)[4])
        self.assertIn(sso_url, target_url_3)
        self.assertIn("SAMLRequest", parsed_query_3)
        request_3 = OneLogin_Saml2_Utils.decode_base64_and_inflate(parsed_query_3["SAMLRequest"][0])
        self.assertIn('ForceAuthn="true"', request_3)
    def testCreateRequest(self):
        """
        Tests the OneLogin_Saml2_Authn_Request Constructor.
        The creation of a deflated SAML Request
        """

        saml_settings = self.loadSettingsJSON()
        settings = OneLogin_Saml2_Settings(saml_settings)
        settings._OneLogin_Saml2_Settings__organization = {
            u'en-US': {
                u'url': u'http://sp.example.com',
                u'name': u'sp_test'
            }
        }

        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
        self.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertNotIn('ProviderName="SP test"', inflated)

        saml_settings['organization'] = {}
        settings = OneLogin_Saml2_Settings(saml_settings)

        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
        self.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertNotIn('ProviderName="SP test"', inflated)
예제 #3
0
    def testLoginIsPassive(self):
        """
        Tests the login method of the OneLogin_Saml2_Auth class
        Case Logout with no parameters. A AuthN Request is built with IsPassive and redirect executed
        """
        settings_info = self.loadSettingsJSON()
        return_to = u'http://example.com/returnto'
        settings_info['idp']['singleSignOnService']['url']

        auth = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info)
        target_url = auth.login(return_to)
        parsed_query = parse_qs(urlparse(target_url)[4])
        sso_url = settings_info['idp']['singleSignOnService']['url']
        self.assertIn(sso_url, target_url)
        self.assertIn('SAMLRequest', parsed_query)
        request = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(parsed_query['SAMLRequest'][0]))
        self.assertNotIn('IsPassive="true"', request)

        auth_2 = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info)
        target_url_2 = auth_2.login(return_to, False, False)
        parsed_query_2 = parse_qs(urlparse(target_url_2)[4])
        self.assertIn(sso_url, target_url_2)
        self.assertIn('SAMLRequest', parsed_query_2)
        request_2 = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(parsed_query_2['SAMLRequest'][0]))
        self.assertNotIn('IsPassive="true"', request_2)

        auth_3 = OneLogin_Saml2_Auth(self.get_request(), old_settings=settings_info)
        target_url_3 = auth_3.login(return_to, False, True)
        parsed_query_3 = parse_qs(urlparse(target_url_3)[4])
        self.assertIn(sso_url, target_url_3)
        self.assertIn('SAMLRequest', parsed_query_3)
        request_3 = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(parsed_query_3['SAMLRequest'][0]))
        self.assertIn('IsPassive="true"', request_3)
    def testCreateRequestAuthContextComparision(self):
        """
        Tests the OneLogin_Saml2_Authn_Request Constructor.
        The creation of a deflated SAML Request with defined AuthnContextComparison
        """
        saml_settings = self.loadSettingsJSON()
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
        self.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertIn(OneLogin_Saml2_Constants.AC_PASSWORD, inflated)
        self.assertNotIn(OneLogin_Saml2_Constants.AC_X509, inflated)

        saml_settings['security']['requestedAuthnContext'] = True
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
        self.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertIn('RequestedAuthnContext Comparison="exact"', inflated)

        saml_settings['security']['requestedAuthnContextComparison'] = 'minimun'
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
        self.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertIn('RequestedAuthnContext Comparison="minimun"', inflated)
예제 #5
0
    def testDeflateBase64Roundtrip(self):
        """
        Tests deflate_and_base64_encode and decode_base64_and_inflate methods of OneLogin_Saml2_Utils
        """
        body = 'Some random string.'
        encoded = OneLogin_Saml2_Utils.deflate_and_base64_encode(body)
        self.assertEqual(OneLogin_Saml2_Utils.decode_base64_and_inflate(encoded), body)

        unicode_body = u'Sömé rändöm nön-äsçïï strïng.'
        unicode_encoded = OneLogin_Saml2_Utils.deflate_and_base64_encode(unicode_body)
        self.assertEqual(OneLogin_Saml2_Utils.decode_base64_and_inflate(unicode_encoded), unicode_body)
예제 #6
0
    def testCreateRequestAuthContext(self):
        """
        Tests the OneLogin_Saml2_Authn_Request Constructor.
        The creation of a deflated SAML Request with defined AuthContext
        """
        saml_settings = self.loadSettingsJSON()
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
        self.assertRegex(inflated, '^<samlp:AuthnRequest')
        self.assertIn(OneLogin_Saml2_Constants.AC_PASSWORD, inflated)
        self.assertNotIn(OneLogin_Saml2_Constants.AC_X509, inflated)

        saml_settings['security']['requestedAuthnContext'] = True
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
        self.assertRegex(inflated, '^<samlp:AuthnRequest')
        self.assertIn(OneLogin_Saml2_Constants.AC_PASSWORD_PROTECTED, inflated)
        self.assertNotIn(OneLogin_Saml2_Constants.AC_X509, inflated)

        del saml_settings['security']['requestedAuthnContext']
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
        self.assertRegex(inflated, '^<samlp:AuthnRequest')
        self.assertIn(OneLogin_Saml2_Constants.AC_PASSWORD_PROTECTED, inflated)
        self.assertNotIn(OneLogin_Saml2_Constants.AC_X509, inflated)

        saml_settings['security']['requestedAuthnContext'] = False
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
        self.assertRegex(inflated, '^<samlp:AuthnRequest')
        self.assertNotIn(OneLogin_Saml2_Constants.AC_PASSWORD_PROTECTED, inflated)
        self.assertNotIn(OneLogin_Saml2_Constants.AC_X509, inflated)

        saml_settings['security']['requestedAuthnContext'] = (OneLogin_Saml2_Constants.AC_PASSWORD_PROTECTED, OneLogin_Saml2_Constants.AC_X509)
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
        self.assertRegex(inflated, '^<samlp:AuthnRequest')
        self.assertIn(OneLogin_Saml2_Constants.AC_PASSWORD_PROTECTED, inflated)
        self.assertIn(OneLogin_Saml2_Constants.AC_X509, inflated)
예제 #7
0
    def testProcessSLOResponseValidDeletingSession(self):
        """
        Tests the process_slo method of the OneLogin_Saml2_Auth class
        Case Valid Logout Response, validating deleting the local session
        """
        request_data = self.get_request()
        message = self.file_contents(join(self.data_path, 'logout_responses', 'logout_response_deflated.xml.base64'))

        # FIXME
        # if (!isset($_SESSION)) {
        #     $_SESSION = array();
        # }
        # $_SESSION['samltest'] = true;

        # In order to avoid the destination problem
        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_data['get_data']['SAMLResponse'] = message
        auth = OneLogin_Saml2_Auth(request_data, old_settings=self.loadSettingsJSON())

        auth.set_strict(True)
        auth.process_slo(False)

        self.assertEqual(len(auth.get_errors()), 0)
예제 #8
0
    def testIsInValidIssuer(self):
        """
        Tests the is_valid method of the OneLogin_Saml2_LogoutResponse
        Case invalid Issuer
        """
        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 = 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)
        plain_message = plain_message.replace('http://idp.example.com/', 'http://invalid.issuer.example.com')
        message = OneLogin_Saml2_Utils.deflate_and_base64_encode(plain_message)

        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('Invalid issuer in the Logout Response', response_2.get_error())
예제 #9
0
    def testProcessSLORequestSignedResponse(self):
        """
        Tests the process_slo method of the OneLogin_Saml2_Auth class
        Case Valid Logout Request, validating the relayState,
        a signed LogoutResponse is created and a redirection executed
        """
        settings_info = self.loadSettingsJSON()
        settings_info["security"]["logoutResponseSigned"] = True
        request_data = self.get_request()
        message = self.file_contents(join(self.data_path, "logout_requests", "logout_request_deflated.xml.base64"))
        # In order to avoid the destination problem
        plain_message = 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_data["get_data"]["SAMLRequest"] = message
        request_data["get_data"]["RelayState"] = "http://relaystate.com"
        auth = OneLogin_Saml2_Auth(request_data, old_settings=settings_info)

        auth.set_strict(True)
        target_url = auth.process_slo(False)
        parsed_query = parse_qs(urlparse(target_url)[4])
        slo_url = settings_info["idp"]["singleLogoutService"]["url"]
        self.assertIn(slo_url, target_url)
        self.assertIn("SAMLResponse", parsed_query)
        self.assertIn("RelayState", parsed_query)
        self.assertIn("SigAlg", parsed_query)
        self.assertIn("Signature", parsed_query)
        self.assertIn("http://relaystate.com", parsed_query["RelayState"])
        self.assertIn(OneLogin_Saml2_Constants.RSA_SHA1, parsed_query["SigAlg"])
예제 #10
0
    def testIsValid(self):
        """
        Tests the is_valid method of the OneLogin_Saml2_LogoutResponse
        """
        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'))

        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)
        try:
            valid = response_2.is_valid(request_data)
            self.assertFalse(valid)
        except Exception as e:
            self.assertIn('The LogoutRequest was received at', e.message)

        plain_message = 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_3 = OneLogin_Saml2_Utils.deflate_and_base64_encode(plain_message)

        response_3 = OneLogin_Saml2_Logout_Response(settings, message_3)
        self.assertTrue(response_3.is_valid(request_data))
def test_suomifi_logout_sp_request(django_client, django_user_model, fixed_saml_id):
    '''Suomi.fi use case #3: sending logout request'''
    oidc_client = create_oidc_client()
    user = create_user(django_user_model)
    create_social_user(user)
    create_oidc_token(user, oidc_client)
    django_client.login(username=TEST_USER, password=TEST_PASSWORD)
    args = {
        'id_token_hint': ID_TOKEN_JWT,
        'post_logout_redirect_uri': REDIRECT_URI,
    }
    logout_page_url = reverse('end-session') + '?{}'.format(urlencode(args))
    logout_page_response = django_client.get(logout_page_url)

    # Logout request results in redirect to Suomi.fi with a SAML message in
    # query parameters. The OIDC token for the user is deleted.
    assert Token.objects.count() == 0
    assert logout_page_response.status_code == 302
    suomifi_redirect = urlparse(logout_page_response.url)
    suomifi_query_params = parse_qs(suomifi_redirect.query)
    suomifi_saml_request = SAMLUtils.decode_base64_and_inflate(suomifi_query_params['SAMLRequest'][0])
    expected_slo_url = urlparse(getattr(settings, 'SOCIAL_AUTH_SUOMIFI_ENABLED_IDPS')['suomifi']['logout_url'])
    expected_logout_request = load_file('suomifi_logout_request.xml')
    expected_logout_signature = load_file('suomifi_logout_signature.b64').decode()
    assert suomifi_redirect[:3] == expected_slo_url[:3]
    assert suomifi_saml_request == expected_logout_request
    assert suomifi_query_params['RelayState'][0] == '{"cli": "test_client", "idx": 0}'
    assert suomifi_query_params['Signature'][0] == expected_logout_signature
def test_suomifi_logout_sp_request_invalid_token(django_client, django_user_model, fixed_saml_id):
    oidc_client = create_oidc_client()
    user = create_user(django_user_model)
    create_social_user(user)
    create_oidc_token(user, oidc_client)
    django_client.login(username=TEST_USER, password=TEST_PASSWORD)
    args = {
        'id_token_hint': ID_TOKEN_JWT_INVALID,
        'post_logout_redirect_uri': REDIRECT_URI,
    }
    logout_page_url = reverse('end-session') + '?{}'.format(urlencode(args))
    logout_page_response = django_client.get(logout_page_url)

    # If the token hint is not recognized but the client has valid session we
    # still perform logout as we are able to deduce enough information to log
    # the client out. We are unable to remove the ID token and we do not have
    # a way to deduce the final redirect after Suomi.fi callback so the
    # RelayState parameter will be missing from the SAML request.
    assert Token.objects.count() == 1
    assert logout_page_response.status_code == 302
    suomifi_redirect = urlparse(logout_page_response.url)
    suomifi_query_params = parse_qs(suomifi_redirect.query)
    suomifi_saml_request = SAMLUtils.decode_base64_and_inflate(suomifi_query_params['SAMLRequest'][0])
    expected_slo_url = urlparse(getattr(settings, 'SOCIAL_AUTH_SUOMIFI_ENABLED_IDPS')['suomifi']['logout_url'])
    expected_logout_request = load_file('suomifi_logout_request.xml')
    expected_logout_signature = load_file('suomifi_logout_without_relaystate_signature.b64').decode()
    assert suomifi_redirect[:3] == expected_slo_url[:3]
    assert suomifi_saml_request == expected_logout_request
    assert 'RelayState' not in suomifi_query_params
    assert suomifi_query_params['Signature'][0] == expected_logout_signature
def test_suomifi_idp_logout(django_client, fixed_saml_id):
    '''Suomi.fi use cases #4: receiving logout request, and #6: sending logout response'''
    create_oidc_client()
    args = {
        'SAMLRequest': load_file('suomifi_idp_logout_request_encoded.b64').decode(),
        'RelayState': RELAY_STATE,
        'SigAlg': 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256',
        'Signature': load_file('suomifi_idp_logout_signature.b64').decode()
    }
    callback_url = reverse('auth_backends:suomifi_logout_callback') + '?{}'.format(urlencode(args))
    callback_response = django_client.get(callback_url)

    # IdP initiated logout request results in redirect to Suomi.fi SLO URL with
    # SAML response and RelayState from request.
    assert callback_response.status_code == 302
    suomifi_redirect = urlparse(callback_response.url)
    suomifi_query_params = parse_qs(suomifi_redirect.query)
    suomifi_saml_response = SAMLUtils.decode_base64_and_inflate(suomifi_query_params['SAMLResponse'][0])
    expected_slo_url = urlparse(getattr(settings, 'SOCIAL_AUTH_SUOMIFI_ENABLED_IDPS')['suomifi']['logout_url'])
    expected_logout_response = load_file('suomifi_idp_logout_response.xml')
    expected_logout_signature = load_file('suomifi_idp_logout_response_signature.b64').decode()
    assert suomifi_redirect[:3] == expected_slo_url[:3]
    assert suomifi_saml_response == expected_logout_response
    assert suomifi_query_params['RelayState'][0] == RELAY_STATE
    assert suomifi_query_params['Signature'][0] == expected_logout_signature
예제 #14
0
    def testProcessSLORequestSignedResponse(self):
        """
        Tests the process_slo method of the OneLogin_Saml2_Auth class
        Case Valid Logout Request, validating the relayState,
        a signed LogoutResponse is created and a redirection executed
        """
        settings_info = self.loadSettingsJSON()
        settings_info['security']['logoutResponseSigned'] = True
        request_data = self.get_request()
        message = self.file_contents(join(self.data_path, 'logout_requests', 'logout_request_deflated.xml.base64'))
        # In order to avoid the destination problem
        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_data['get_data']['SAMLRequest'] = message
        request_data['get_data']['RelayState'] = 'http://relaystate.com'
        auth = OneLogin_Saml2_Auth(request_data, old_settings=settings_info)

        auth.set_strict(True)
        target_url = auth.process_slo(False)
        parsed_query = parse_qs(urlparse(target_url)[4])
        slo_url = settings_info['idp']['singleLogoutService']['url']
        self.assertIn(slo_url, target_url)
        self.assertIn('SAMLResponse', parsed_query)
        self.assertIn('RelayState', parsed_query)
        self.assertIn('SigAlg', parsed_query)
        self.assertIn('Signature', parsed_query)
        self.assertIn('http://relaystate.com', parsed_query['RelayState'])
        self.assertIn(OneLogin_Saml2_Constants.RSA_SHA1, parsed_query['SigAlg'])
예제 #15
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.assertRegexpMatches(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.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertRegexpMatches(inflated, 'AssertionConsumerServiceURL="http://stuff.com/endpoints/endpoints/acs.php">')
        self.assertRegexpMatches(inflated, '<saml:Issuer>http://stuff.com/endpoints/metadata.php</saml:Issuer>')
        self.assertRegexpMatches(inflated, 'Format="urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted"')
        self.assertRegexpMatches(inflated, 'ProviderName="SP prueba"')
예제 #16
0
 def testGetIDFromDeflatedSAMLLogoutRequest(self):
     """
     Tests the get_id method of the OneLogin_Saml2_LogoutRequest
     """
     deflated_logout_request = self.file_contents(join(self.data_path, 'logout_requests', 'logout_request_deflated.xml.base64'))
     logout_request = OneLogin_Saml2_Utils.decode_base64_and_inflate(deflated_logout_request)
     id = OneLogin_Saml2_Logout_Request.get_id(logout_request)
     self.assertEqual('ONELOGIN_21584ccdfaca36a145ae990442dcd96bfe60151e', id)
예제 #17
0
파일: auth.py 프로젝트: teeberg/python-saml
    def process_slo(self, keep_local_session=False, request_id=None, delete_session_cb=None):
        """
        Process the SAML Logout Response / Logout Request sent by the IdP.

        :param keep_local_session: When false will destroy the local session, otherwise will destroy it
        :type keep_local_session: bool

        :param request_id: The ID of the LogoutRequest sent by this SP to the IdP
        :type request_id: string

        :returns: Redirection url
        """
        self.__errors = []

        if 'get_data' in self.__request_data and 'SAMLResponse' in self.__request_data['get_data']:
            logout_response = OneLogin_Saml2_Logout_Response(self.__settings, self.__request_data['get_data']['SAMLResponse'])
            if not logout_response.is_valid(self.__request_data, request_id):
                self.__errors.append('invalid_logout_response')
                self.__error_reason = logout_response.get_error()
            elif logout_response.get_status() != OneLogin_Saml2_Constants.STATUS_SUCCESS:
                self.__errors.append('logout_not_success')
            elif not keep_local_session:
                OneLogin_Saml2_Utils.delete_local_session(delete_session_cb)

        elif 'get_data' in self.__request_data and 'SAMLRequest' in self.__request_data['get_data']:
            logout_request = OneLogin_Saml2_Logout_Request(self.__settings, self.__request_data['get_data']['SAMLRequest'])
            if not logout_request.is_valid(self.__request_data):
                self.__errors.append('invalid_logout_request')
                self.__error_reason = logout_request.get_error()
            else:
                if not keep_local_session:
                    OneLogin_Saml2_Utils.delete_local_session(delete_session_cb)

                in_response_to = OneLogin_Saml2_Logout_Request.get_id(OneLogin_Saml2_Utils.decode_base64_and_inflate(self.__request_data['get_data']['SAMLRequest']))
                response_builder = OneLogin_Saml2_Logout_Response(self.__settings)
                response_builder.build(in_response_to)
                logout_response = response_builder.get_response()

                parameters = {'SAMLResponse': logout_response}
                if 'RelayState' in self.__request_data['get_data']:
                    parameters['RelayState'] = self.__request_data['get_data']['RelayState']

                security = self.__settings.get_security_data()
                if 'logoutResponseSigned' in security and security['logoutResponseSigned']:
                    parameters['SigAlg'] = OneLogin_Saml2_Constants.RSA_SHA1
                    parameters['Signature'] = self.build_response_signature(logout_response, parameters.get('RelayState', None))

                return self.redirect_to(self.get_slo_url(), parameters)
        else:
            self.__errors.append('invalid_binding')
            raise OneLogin_Saml2_Error(
                'SAML LogoutRequest/LogoutResponse not found. Only supported HTTP_REDIRECT Binding',
                OneLogin_Saml2_Error.SAML_LOGOUTMESSAGE_NOT_FOUND
            )
예제 #18
0
 def testGetID(self):
     """
     Tests the get_id method of the OneLogin_Saml2_Authn_Request.
     """
     saml_settings = self.loadSettingsJSON()
     settings = OneLogin_Saml2_Settings(saml_settings)
     authn_request = OneLogin_Saml2_Authn_Request(settings)
     authn_request_encoded = authn_request.get_request()
     inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
     document = OneLogin_Saml2_XML.to_etree(inflated)
     self.assertEqual(authn_request.get_id(), document.get('ID', None))
예제 #19
0
    def testAttributeConsumingService(self):
        """
        Tests that the attributeConsumingServiceIndex is present as an attribute
        """
        saml_settings = self.loadSettingsJSON()
        settings = OneLogin_Saml2_Settings(saml_settings)

        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))

        self.assertNotIn('AttributeConsumingServiceIndex="1"', inflated)

        saml_settings = self.loadSettingsJSON('settings4.json')
        settings = OneLogin_Saml2_Settings(saml_settings)

        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))

        self.assertRegex(inflated, 'AttributeConsumingServiceIndex="1"')
예제 #20
0
    def __init__(self, settings, response=None):
        """
        Constructs a Logout Response object (Initialize params from settings
        and if provided load the Logout Response.

        Arguments are:
            * (OneLogin_Saml2_Settings)   settings. Setting data
            * (string)                    response. An UUEncoded SAML Logout
                                                    response from the IdP.
        """
        self.__settings = settings
        if response is not None:
            self.__logout_response = OneLogin_Saml2_Utils.decode_base64_and_inflate(response)
            self.document = parseString(self.__logout_response)
예제 #21
0
    def testCreateRequestIsPassive(self):
        """
        Tests the OneLogin_Saml2_Authn_Request Constructor.
        The creation of a deflated SAML Request with IsPassive="true"
        """
        saml_settings = self.loadSettingsJSON()
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded))
        self.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertNotIn('IsPassive="true"', inflated)

        authn_request_2 = OneLogin_Saml2_Authn_Request(settings, False, False)
        authn_request_encoded_2 = authn_request_2.get_request()
        inflated_2 = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded_2))
        self.assertRegexpMatches(inflated_2, '^<samlp:AuthnRequest')
        self.assertNotIn('IsPassive="true"', inflated_2)

        authn_request_3 = OneLogin_Saml2_Authn_Request(settings, False, True)
        authn_request_encoded_3 = authn_request_3.get_request()
        inflated_3 = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(authn_request_encoded_3))
        self.assertRegexpMatches(inflated_3, '^<samlp:AuthnRequest')
        self.assertIn('IsPassive="true"', inflated_3)
예제 #22
0
    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.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')
예제 #23
0
 def testCreateDeflatedSAMLRequestURLParameter(self):
     """
     Tests the OneLogin_Saml2_Authn_Request Constructor.
     The creation of a deflated SAML Request
     """
     authn_request = OneLogin_Saml2_Authn_Request(self.__settings)
     parameters = {
         'SAMLRequest': authn_request.get_request()
     }
     auth_url = OneLogin_Saml2_Utils.redirect('http://idp.example.com/SSOService.php', parameters, True)
     self.assertRegexpMatches(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.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
예제 #24
0
 def testConstructorWithoutNameIdFormat(self):
     """
     Tests the OneLogin_Saml2_LogoutRequest Constructor.
     Case: Checks that NameIDFormat is not added
     """
     settings_info = self.loadSettingsJSON()
     name_id = 'ONELOGIN_1e442c129e1f822c8096086a1103c5ee2c7cae1c'
     name_id_format = 'urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified'
     settings_info['sp']['NameIDFormat'] = name_id_format
     settings = OneLogin_Saml2_Settings(settings_info)
     logout_request = OneLogin_Saml2_Logout_Request(settings, name_id=name_id)
     logout_request_xml = OneLogin_Saml2_Utils.decode_base64_and_inflate(logout_request.get_request())
     name_id_data = OneLogin_Saml2_Logout_Request.get_nameid_data(logout_request_xml)
     expected_name_id_data = {
         'Value': name_id
     }
     self.assertEqual(expected_name_id_data, name_id_data)
예제 #25
0
    def testGetStatus(self):
        """
        Tests the get_status method 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)
        status = response.get_status()
        self.assertEquals(status, OneLogin_Saml2_Constants.STATUS_SUCCESS)

        dom = parseString(OneLogin_Saml2_Utils.decode_base64_and_inflate(message))
        status_code_node = dom.getElementsByTagName('samlp:StatusCode')[0]
        status_code_node.parentNode.removeChild(status_code_node)
        xml = dom.toxml()
        message_2 = OneLogin_Saml2_Utils.deflate_and_base64_encode(xml)
        response_2 = OneLogin_Saml2_Logout_Response(settings, message_2)
        self.assertIsNone(response_2.get_status())
    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 = compat.to_string(OneLogin_Saml2_Utils.decode_base64_and_inflate(payload))
        self.assertRegexpMatches(inflated, '^<samlp:LogoutRequest')
예제 #27
0
    def testProcessSLORequestNotOnOrAfterFailed(self):
        """
        Tests the process_slo method of the OneLogin_Saml2_Auth class
        Case Logout Request NotOnOrAfter failed
        """
        request_data = self.get_request()
        message = self.file_contents(join(self.data_path, 'logout_requests', 'invalids', 'not_after_failed.xml.base64'))
        # In order to avoid the destination problem
        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_data['get_data']['SAMLRequest'] = message
        auth = OneLogin_Saml2_Auth(request_data, old_settings=self.loadSettingsJSON())

        auth.set_strict(True)
        auth.process_slo(True)
        self.assertEqual(auth.get_errors(), ['invalid_logout_request'])
예제 #28
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')
예제 #29
0
 def testConstructorWithNameIdFormatOnSettings(self):
     """
     Tests the OneLogin_Saml2_LogoutRequest Constructor.
     Case: Defines NameIDFormat from settings
     """
     settings_info = self.loadSettingsJSON()
     name_id = 'ONELOGIN_1e442c129e1f822c8096086a1103c5ee2c7cae1c'
     name_id_format = 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
     settings_info['sp']['NameIDFormat'] = name_id_format
     settings = OneLogin_Saml2_Settings(settings_info)
     logout_request = OneLogin_Saml2_Logout_Request(settings, name_id=name_id)
     logout_request_xml = OneLogin_Saml2_Utils.decode_base64_and_inflate(logout_request.get_request())
     name_id_data = OneLogin_Saml2_Logout_Request.get_nameid_data(logout_request_xml)
     expected_name_id_data = {
         'Value': name_id,
         'Format': name_id_format
     }
     self.assertEqual(expected_name_id_data, name_id_data)
예제 #30
0
    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)
예제 #31
0
    def __init__(self, settings, response=None):
        """
        Constructs a Logout Response object (Initialize params from settings
        and if provided load the Logout Response.

        Arguments are:
            * (OneLogin_Saml2_Settings)   settings. Setting data
            * (string)                    response. An UUEncoded SAML Logout
                                                    response from the IdP.
        """
        self.__settings = settings
        self.__error = None
        self.id = None

        if response is not None:
            self.__logout_response = OneLogin_Saml2_Utils.decode_base64_and_inflate(
                response)
            self.document = parseString(self.__logout_response)
            self.id = self.document.documentElement.getAttribute('ID')
예제 #32
0
    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)
        try:
            valid = response_2.is_valid(request_data)
            self.assertFalse(valid)
        except Exception as e:
            self.assertIn('The LogoutRequest was received at', str(e))

        # 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))
예제 #33
0
    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.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')
예제 #34
0
    def __init__(self, settings, response=None):
        """
        Constructs a Logout Response object (Initialize params from settings
        and if provided load the Logout Response.

        Arguments are:
            * (OneLogin_Saml2_Settings)   settings. Setting data
            * (string)                    response. An UUEncoded SAML Logout
                                                    response from the IdP.
        """
        self.__settings = settings
        self.__error = None
        self.id = None

        if response is not None:
            self.__logout_response = compat.to_string(
                OneLogin_Saml2_Utils.decode_base64_and_inflate(
                    response, ignore_zip=True))
            self.document = OneLogin_Saml2_XML.to_etree(self.__logout_response)
            self.id = self.document.get('ID', None)
예제 #35
0
    def testGetStatus(self):
        """
        Tests the get_status method 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)
        status = response.get_status()
        self.assertEquals(status, OneLogin_Saml2_Constants.STATUS_SUCCESS)

        dom = parseString(
            OneLogin_Saml2_Utils.decode_base64_and_inflate(message))
        status_code_node = dom.getElementsByTagName('samlp:StatusCode')[0]
        status_code_node.parentNode.removeChild(status_code_node)
        xml = dom.toxml()
        message_2 = OneLogin_Saml2_Utils.deflate_and_base64_encode(xml)
        response_2 = OneLogin_Saml2_Logout_Response(settings, message_2)
        self.assertIsNone(response_2.get_status())
예제 #36
0
    def testConstructorEncryptIdUsingX509certMulti(self):
        """
        Tests the OneLogin_Saml2_LogoutRequest Constructor.
        Case: Able to generate encryptedID with MultiCert
        """
        settings_info = self.loadSettingsJSON('settings8.json')
        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.assertRegex(logout_url, r'^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')
        self.assertRegex(inflated, '<saml:EncryptedID>')
예제 #37
0
 def modify_start_url(self, start_url):
     """
     Given a SAML redirect URL, parse it and change the ID to
     a consistent value, so the request is always identical.
     """
     # Parse the SAML Request URL to get the XML being sent to TestShib
     url_parts = urlparse(start_url)
     query = dict(
         (k, v[0]) for (k, v) in parse_qs(url_parts.query).iteritems())
     xml = OneLogin_Saml2_Utils.decode_base64_and_inflate(
         query['SAMLRequest'])
     # Modify the XML:
     xml, changed = re.subn(r'ID="[^"]+"', 'ID="TEST_ID"', xml)
     self.assertEqual(changed, 1)
     # Update the URL to use the modified query string:
     query['SAMLRequest'] = OneLogin_Saml2_Utils.deflate_and_base64_encode(
         xml)
     url_parts = list(url_parts)
     url_parts[4] = urlencode(query)
     return urlunparse(url_parts)
예제 #38
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.assertRegexpMatches(
            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.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertRegexpMatches(
            inflated,
            'AssertionConsumerServiceURL="http://stuff.com/endpoints/endpoints/acs.php">'
        )
        self.assertRegexpMatches(
            inflated,
            '<saml:Issuer>http://stuff.com/endpoints/metadata.php</saml:Issuer>'
        )
        self.assertRegexpMatches(
            inflated,
            'Format="urn:oasis:names:tc:SAML:2.0:nameid-format:encrypted"')
        self.assertRegexpMatches(inflated, 'ProviderName="SP prueba"')
예제 #39
0
 def logout(self, to=None):  # pylint: disable=R0201,C0111,C0103
     # Check and set return_to
     return_to = self.settings["auth"]["logout_default_redirect_url"]
     if to is not None and to in self.settings["auth"][
             "logout_allowed_redirect_urls"]:
         return_to = to
     # Create logout request object
     saml_auth = OneLogin_Saml2_Auth(
         self._prepare_request_object(cherrypy.request),
         self.settings["saml"])
     logout_redirect_url = saml_auth.logout(return_to=return_to)
     # Clear session now
     cherrypy.session.clear()
     cherrypy.session.regenerate()
     # Redirect in case of HTTP-REDIRECT binding
     if self.settings["saml"]["idp"]["singleLogoutService"]["binding"] != \
             "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST":
         raise cherrypy.HTTPRedirect(logout_redirect_url)
     # Prepare request for HTTP-POST
     parsed_url = urlsplit(logout_redirect_url)
     saml_post_action = urlunsplit(parsed_url._replace(query=""))
     saml_post_parameters = parse_qs(parsed_url.query)
     saml_security = saml_auth.get_settings().get_security_data()
     request = OneLogin_Saml2_Utils.decode_base64_and_inflate(
         saml_post_parameters["SAMLRequest"][0])
     # Prepare signed request if needed
     if saml_security.get("logoutRequestSigned", False):
         request = self._sign_saml_request(request, saml_auth,
                                           saml_security)
     # Perform HTTP-POST binding
     return [{
         "action":
         saml_post_action,
         "parameters": [{
             "name": "SAMLRequest",
             "value": request
         }, {
             "name": "RelayState",
             "value": saml_post_parameters["RelayState"][0]
         }]
     }]
예제 #40
0
    def test_saml_request_omits_authentication_context(self):
        # Make sure RequestedAuthnContext doesn't show up in SAMLReuqest
        with self.settings(TOKEN_AUTH=TOKEN_AUTH_SETTINGS):
            request = self._request('get',
                                    '/sso/redirect',
                                    HTTP_HOST='www.stuff.com')
            auth_backend = SAMLAuthentication(request)

            sso_url = urllib.parse.urlparse(auth_backend.sso_url())
            query = urllib.parse.parse_qs(sso_url.query)
            self.assertEqual(
                urllib.parse.urlunparse((sso_url.scheme, sso_url.netloc,
                                         sso_url.path, None, None, None)),
                TOKEN_AUTH_SETTINGS['idp']['singleSignOnService']['url'])
            saml_request = query['SAMLRequest'][0]
            saml_xml = OneLogin_Saml2_Utils.decode_base64_and_inflate(
                saml_request)
            pre = {'samlp': "urn:oasis:names:tc:SAML:2.0:protocol"}
            tree = ET.fromstring(saml_xml)
            rac = tree.findall('samlp:RequestedAuthnContext', pre)
            self.assertEqual(len(rac), 0)
예제 #41
0
    def testProcessSLORequestNotOnOrAfterFailed(self):
        """
        Tests the process_slo method of the OneLogin_Saml2_Auth class
        Case Logout Request NotOnOrAfter failed
        """
        request_data = self.get_request()
        message = self.file_contents(
            join(self.data_path, 'logout_requests', 'invalids',
                 'not_after_failed.xml.base64'))
        # In order to avoid the destination problem
        plain_message = 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_data['get_data']['SAMLRequest'] = message
        auth = OneLogin_Saml2_Auth(request_data,
                                   old_settings=self.loadSettingsJSON())

        auth.set_strict(True)
        auth.process_slo(True)
        self.assertEqual(auth.get_errors(), ['invalid_logout_request'])
예제 #42
0
def test_suomifi_login_request(django_client, fixed_saml_id):
    '''Suomi.fi use case #1: sending authentication request'''
    create_oidc_client()
    args = {
        'client_id': CLIENT_ID,
        'redirect_uri': REDIRECT_URI,
        'response_type': 'code',
    }
    auth_page_url = reverse('authorize') + '?{}'.format(urlencode(args))
    auth_page_response = django_client.get(auth_page_url, follow=True)

    # As we have configured only one login method Tunnistamo will automatically
    # redirect there. We'll verify the final redirect here.
    suomifi_redirect = urlparse(auth_page_response.redirect_chain[-1][0])
    suomifi_query_params = parse_qs(suomifi_redirect.query)
    suomifi_saml_request = SAMLUtils.decode_base64_and_inflate(suomifi_query_params['SAMLRequest'][0])
    expected_sso_url = urlparse(getattr(settings, 'SOCIAL_AUTH_SUOMIFI_ENABLED_IDPS')['suomifi']['url'])
    expected_login_request = load_file('suomifi_login_request.xml')
    expected_login_signature = load_file('suomifi_login_signature.b64').decode()
    assert suomifi_redirect[:3] == expected_sso_url[:3]
    assert suomifi_saml_request == expected_login_request
    assert suomifi_query_params['Signature'][0] == expected_login_signature
예제 #43
0
    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)
예제 #44
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)
예제 #45
0
def logout_view(request, *args, **kwargs):
    backend = request.backend
    logout(request)

    # Пользователя разлогинили, теперь нужно ответить провайдеру.
    # Для начала нужно узнать, от какого именно IdentityProvider'а пришёл запрос.
    # Как минимму OneLogin не присылает в запросе никаких опознавательных знаков кроме атрибута Issuer.
    # В Issuer у него находится путь к его метадате. В конфиге тот же путь надо указать в entity_id.

    # вынимаем значение Issuer
    request_str = compat.to_string(
        OneLogin_Saml2_Utils.decode_base64_and_inflate(
            request.GET['SAMLRequest']))
    xml_doc = OneLogin_Saml2_XML.to_etree(request_str)
    issuer_nodes = OneLogin_Saml2_XML.query(
        xml_doc, '/samlp:LogoutRequest/saml:Issuer')
    if len(issuer_nodes) == 0:
        raise ValueError('no Issuer in logout request: ' + request_str)
    issuer = issuer_nodes[0].text

    # ищем имя IDP
    idp_configs = backend.setting('ENABLED_IDPS')
    idp_name = next((name for name, cfg in idp_configs.items()
                     if cfg.get('entity_id') == issuer), None)
    if idp_name is None:
        raise ValueError(
            f"IDP not found for Issuer '{issuer}' in logout request: " +
            request_str)

    # формируем адрес редиректа
    idp = backend.get_idp(idp_name)
    if idp.slo_config == {}:  # если конфига slo нет
        url = settings.LOGOUT_REDIRECT_URL
    else:
        url = backend._create_saml_auth(
            idp, remove_signature_from_get=True).process_slo()

    return HttpResponseRedirect(url)
예제 #46
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')
예제 #47
0
    def testProcessSLOResponseRequestId(self):
        """
        Tests the process_slo method of the OneLogin_Saml2_Auth class
        Case Logout Response with valid and invalid Request ID
        """
        request_data = self.get_request()
        message = self.file_contents(join(self.data_path, 'logout_responses', 'logout_response_deflated.xml.base64'))
        # In order to avoid the destination problem
        plain_message = 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_data['get_data']['SAMLResponse'] = message
        auth = OneLogin_Saml2_Auth(request_data, old_settings=self.loadSettingsJSON())

        request_id = 'wrongID'
        auth.set_strict(True)
        auth.process_slo(True, request_id)
        self.assertEqual(auth.get_errors(), ['invalid_logout_response'])

        request_id = 'ONELOGIN_21584ccdfaca36a145ae990442dcd96bfe60151e'
        auth.process_slo(True, request_id)
        self.assertEqual(len(auth.get_errors()), 0)
예제 #48
0
    def testProcessSLOResponseValid(self):
        """
        Tests the process_slo method of the OneLogin_Saml2_Auth class
        Case Valid Logout Response
        """
        request_data = self.get_request()
        message = self.file_contents(join(self.data_path, 'logout_responses', 'logout_response_deflated.xml.base64'))
        # In order to avoid the destination problem
        plain_message = 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_data['get_data']['SAMLResponse'] = message
        auth = OneLogin_Saml2_Auth(request_data, old_settings=self.loadSettingsJSON())

        # FIXME
        # if (!isset($_SESSION)) {
        #     $_SESSION = array();
        # }
        # $_SESSION['samltest'] = true;

        auth.set_strict(True)
        auth.process_slo(True)
        self.assertEqual(len(auth.get_errors()), 0)
예제 #49
0
def test_suomifi_logout_sp_request_invalid_token(django_client,
                                                 django_user_model,
                                                 fixed_saml_id):
    oidc_client = create_oidc_client()
    user = create_user(django_user_model)
    create_social_user(user)
    create_oidc_token(user, oidc_client)
    django_client.login(username=TEST_USER, password=TEST_PASSWORD)
    args = {
        'id_token_hint': ID_TOKEN_JWT_INVALID,
        'post_logout_redirect_uri': REDIRECT_URI,
    }
    logout_page_url = reverse('end-session') + '?{}'.format(urlencode(args))
    logout_page_response = django_client.get(logout_page_url)

    # If the token hint is not recognized but the client has valid session we
    # still perform logout as we are able to deduce enough information to log
    # the client out. We are unable to remove the ID token and we do not have
    # a way to deduce the final redirect after Suomi.fi callback so the
    # RelayState parameter will be missing from the SAML request.
    assert Token.objects.count() == 1
    assert logout_page_response.status_code == 302
    suomifi_redirect = urlparse(logout_page_response.url)
    suomifi_query_params = parse_qs(suomifi_redirect.query)
    suomifi_saml_request = SAMLUtils.decode_base64_and_inflate(
        suomifi_query_params['SAMLRequest'][0])
    expected_slo_url = urlparse(
        getattr(settings,
                'SOCIAL_AUTH_SUOMIFI_ENABLED_IDPS')['suomifi']['logout_url'])
    expected_logout_request = load_file('suomifi_logout_request.xml')
    expected_logout_signature = load_file(
        'suomifi_logout_without_relaystate_signature.b64').decode()
    assert suomifi_redirect[:3] == expected_slo_url[:3]
    assert suomifi_saml_request == expected_logout_request
    assert 'RelayState' not in suomifi_query_params
    assert suomifi_query_params['Signature'][0] == expected_logout_signature
예제 #50
0
    def __init__(self,
                 settings,
                 request=None,
                 name_id=None,
                 session_index=None,
                 nq=None):
        """
        Constructs the Logout Request object.

        :param settings: Setting data
        :type settings: OneLogin_Saml2_Settings

        :param request: Optional. A LogoutRequest to be loaded instead build one.
        :type request: string

        :param name_id: The NameID that will be set in the LogoutRequest.
        :type name_id: string

        :param session_index: SessionIndex that identifies the session of the user.
        :type session_index: string

        :param nq: IDP Name Qualifier
        :type: string
        """
        self.__settings = settings
        self.__error = None
        self.id = None

        if request is None:
            sp_data = self.__settings.get_sp_data()
            idp_data = self.__settings.get_idp_data()
            security = self.__settings.get_security_data()

            uid = OneLogin_Saml2_Utils.generate_unique_id()
            self.id = uid

            issue_instant = OneLogin_Saml2_Utils.parse_time_to_SAML(
                OneLogin_Saml2_Utils.now())

            cert = None
            if security['nameIdEncrypted']:
                cert = idp_data['x509cert']

            if name_id is not None:
                name_id_format = sp_data['NameIDFormat']
                sp_name_qualifier = None
            else:
                name_id = idp_data['entityId']
                name_id_format = OneLogin_Saml2_Constants.NAMEID_ENTITY
                sp_name_qualifier = sp_data['entityId']

            name_id_obj = OneLogin_Saml2_Utils.generate_name_id(
                name_id,
                sp_name_qualifier,
                name_id_format,
                cert,
                nq=nq,
            )

            if session_index:
                session_index_str = '<samlp:SessionIndex>%s</samlp:SessionIndex>' % session_index
            else:
                session_index_str = ''

            logout_request = OneLogin_Saml2_Templates.LOGOUT_REQUEST % \
                {
                    'id': uid,
                    'issue_instant': issue_instant,
                    'single_logout_url': idp_data['singleLogoutService']['url'],
                    'entity_id': sp_data['entityId'],
                    'name_id': name_id_obj,
                    'session_index': session_index_str,
                }
        else:
            logout_request = OneLogin_Saml2_Utils.decode_base64_and_inflate(
                request, ignore_zip=True)
            self.id = self.get_id(logout_request)

        self.__logout_request = logout_request
예제 #51
0
    def testIsValidSign(self):
        """
        Tests the is_valid method of the OneLogin_Saml2_LogoutRequest
        """
        request_data = {
            'http_host': 'example.com',
            'script_name': 'index.html',
            'get_data': {
                'SAMLRequest':
                'lVLBitswEP0Vo7tjeWzJtki8LIRCYLvbNksPewmyPc6K2pJqyXQ/v1LSQlroQi/DMJr33rwZbZ2cJysezNms/gt+X9H55G2etBOXlx1ZFy2MdMoJLWd0wvfieP/xQcCGCrsYb3ozkRvI+wjpHC5eGU2Sw35HTg3lA8hqZFwWFcMKsStpxbEsxoLXeQN9OdY1VAgk+YqLC8gdCUQB7tyKB+281D6UaF6mtEiBPudcABcMXkiyD26Ulv6CevXeOpFlVvlunb5ttEmV3ZjlnGn8YTRO5qx0NuBs8kzpAd829tXeucmR5NH4J/203I8el6gFRUqbFPJnyEV51Wq30by4TLW0/9ZyarYTxt4sBsjUYLMZvRykl1Fxm90SXVkfwx4P++T4KSafVzmpUcVJ/sfSrQZJPphllv79W8WKGtLx0ir8IrVTqD1pT2MH3QAMSs4KTvui71jeFFiwirOmprwPkYW063+5uRq4urHiiC4e8hCX3J5wqAEGaPpw9XB5JmkBdeDqSlkz6CmUXdl0Qae5kv2F/1384wu3PwE=',
                'RelayState':
                '_1037fbc88ec82ce8e770b2bed1119747bb812a07e6',
                'SigAlg':
                'http://www.w3.org/2000/09/xmldsig#rsa-sha1',
                'Signature':
                'XCwCyI5cs7WhiJlB5ktSlWxSBxv+6q2xT3c8L7dLV6NQG9LHWhN7gf8qNsahSXfCzA0Ey9dp5BQ0EdRvAk2DIzKmJY6e3hvAIEp1zglHNjzkgcQmZCcrkK9Czi2Y1WkjOwR/WgUTUWsGJAVqVvlRZuS3zk3nxMrLH6f7toyvuJc='
            }
        }
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())
        current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data)

        request = OneLogin_Saml2_Utils.decode_base64_and_inflate(
            request_data['get_data']['SAMLRequest'])

        settings.set_strict(False)
        logout_request = OneLogin_Saml2_Logout_Request(settings,
                                                       b64encode(request))
        self.assertTrue(logout_request.is_valid(request_data))

        relayState = request_data['get_data']['RelayState']
        del request_data['get_data']['RelayState']
        self.assertFalse(logout_request.is_valid(request_data))
        request_data['get_data']['RelayState'] = relayState

        settings.set_strict(True)
        logout_request2 = OneLogin_Saml2_Logout_Request(
            settings, b64encode(request))
        self.assertFalse(logout_request2.is_valid(request_data))
        self.assertIn('The LogoutRequest was received at',
                      logout_request2.get_error())

        settings.set_strict(False)
        old_signature = request_data['get_data']['Signature']
        request_data['get_data'][
            'Signature'] = 'vfWbbc47PkP3ejx4bjKsRX7lo9Ml1WRoE5J5owF/0mnyKHfSY6XbhO1wwjBV5vWdrUVX+xp6slHyAf4YoAsXFS0qhan6txDiZY4Oec6yE+l10iZbzvie06I4GPak4QrQ4gAyXOSzwCrRmJu4gnpeUxZ6IqKtdrKfAYRAcVf3333='
        logout_request3 = OneLogin_Saml2_Logout_Request(
            settings, b64encode(request))
        self.assertFalse(logout_request3.is_valid(request_data))
        self.assertIn('Signature validation failed. Logout Request rejected',
                      logout_request3.get_error())

        request_data['get_data']['Signature'] = old_signature
        old_signature_algorithm = request_data['get_data']['SigAlg']
        del request_data['get_data']['SigAlg']
        self.assertTrue(logout_request3.is_valid(request_data))

        request_data['get_data'][
            'RelayState'] = 'http://example.com/relaystate'
        self.assertFalse(logout_request3.is_valid(request_data))
        self.assertIn('Signature validation failed. Logout Request rejected',
                      logout_request3.get_error())

        settings.set_strict(True)
        request_2 = request.replace(
            'https://pitbulk.no-ip.org/newonelogin/demo1/index.php?sls',
            current_url)
        request_2 = request_2.replace(
            'https://pitbulk.no-ip.org/simplesaml/saml2/idp/metadata.php',
            'http://idp.example.com/')
        request_data['get_data'][
            'SAMLRequest'] = OneLogin_Saml2_Utils.deflate_and_base64_encode(
                request_2)
        logout_request4 = OneLogin_Saml2_Logout_Request(
            settings, b64encode(request_2))
        self.assertFalse(logout_request4.is_valid(request_data))
        self.assertIn('Signature validation failed. Logout Request rejected',
                      logout_request4.get_error())

        settings.set_strict(False)
        logout_request5 = OneLogin_Saml2_Logout_Request(
            settings, b64encode(request_2))
        self.assertFalse(logout_request5.is_valid(request_data))
        self.assertIn('Signature validation failed. Logout Request rejected',
                      logout_request5.get_error())

        request_data['get_data'][
            'SigAlg'] = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1'
        self.assertFalse(logout_request5.is_valid(request_data))
        self.assertIn('Signature validation failed. Logout Request rejected',
                      logout_request5.get_error())

        settings_info = self.loadSettingsJSON()
        settings_info['strict'] = True
        settings_info['security']['wantMessagesSigned'] = True
        settings = OneLogin_Saml2_Settings(settings_info)
        request_data['get_data']['SigAlg'] = old_signature_algorithm
        old_signature = request_data['get_data']['Signature']
        del request_data['get_data']['Signature']
        logout_request6 = OneLogin_Saml2_Logout_Request(
            settings, b64encode(request_2))
        self.assertFalse(logout_request6.is_valid(request_data))
        self.assertIn(
            'The Message of the Logout Request is not signed and the SP require it',
            logout_request6.get_error())

        request_data['get_data']['Signature'] = old_signature
        settings_info['idp'][
            'certFingerprint'] = 'afe71c28ef740bc87425be13a2263d37971da1f9'
        del settings_info['idp']['x509cert']
        settings_2 = OneLogin_Saml2_Settings(settings_info)
        logout_request7 = OneLogin_Saml2_Logout_Request(
            settings_2, b64encode(request_2))
        self.assertFalse(logout_request7.is_valid(request_data))
        self.assertEqual(
            'In order to validate the sign on the Logout Request, the x509cert of the IdP is required',
            logout_request7.get_error())
예제 #52
0
 def decode_saml_request(self, encoded_saml_request):
     return str(
         OneLogin_Saml2_Utils.decode_base64_and_inflate(
             encoded_saml_request))
예제 #53
0
    def testIsInValidSign(self):
        """
        Tests the is_valid method of the OneLogin_Saml2_LogoutResponse
        """
        request_data = {
            'http_host': 'example.com',
            'script_name': 'index.html',
            'get_data': {}
        }
        settings = OneLogin_Saml2_Settings(self.loadSettingsJSON())

        settings.set_strict(False)
        request_data['get_data'] = {
            'SAMLResponse': 'fZJva8IwEMa/Ssl7TZrW/gnqGHMMwSlM8cXeyLU9NaxNQi9lfvxVZczB5ptwSe733MPdjQma2qmFPdjOvyE5awiDU1MbUpevCetaoyyQJmWgQVK+VOvH14WSQ6Fca70tbc1ukPsEEGHrtTUsmM8mbDfKUhnFci8gliGINI/yXIAAiYnsw6JIRgWWAKlkwRZb6skJ64V6nKjDuSEPxvdPIowHIhpIsQkTFaYqSt9ZMEPy2oC/UEfvHSnOnfZFV38MjR1oN7TtgRv8tAZre9CGV9jYkGtT4Wnoju6Bauprme/ebOyErZbPi9XLfLnDoohwhHGc5WVSVhjCKM6rBMpYQpWJrIizfZ4IZNPxuTPqYrmd/m+EdONqPOfy8yG5rhxv0EMFHs52xvxWaHyd3tqD7+j37clWGGyh7vD+POiSrdZdWSIR49NrhR9R/teGTL8A',
            'RelayState': 'https://pitbulk.no-ip.org/newonelogin/demo1/index.php',
            'SigAlg': 'http://www.w3.org/2000/09/xmldsig#rsa-sha1',
            'Signature': 'vfWbbc47PkP3ejx4bjKsRX7lo9Ml1WRoE5J5owF/0mnyKHfSY6XbhO1wwjBV5vWdrUVX+xp6slHyAf4YoAsXFS0qhan6txDiZY4Oec6yE+l10iZbzvie06I4GPak4QrQ4gAyXOSzwCrRmJu4gnpeUxZ6IqKtdrKfAYRAcVfNKGA='
        }
        response = OneLogin_Saml2_Logout_Response(settings, request_data['get_data']['SAMLResponse'])
        self.assertTrue(response.is_valid(request_data))

        relayState = request_data['get_data']['RelayState']
        del request_data['get_data']['RelayState']
        inv_response = OneLogin_Saml2_Logout_Response(settings, request_data['get_data']['SAMLResponse'])
        self.assertFalse(inv_response.is_valid(request_data))
        request_data['get_data']['RelayState'] = relayState

        settings.set_strict(True)
        response_2 = OneLogin_Saml2_Logout_Response(settings, request_data['get_data']['SAMLResponse'])
        self.assertFalse(response_2.is_valid(request_data))
        self.assertIn('Invalid issuer in the Logout Response', response_2.get_error())

        settings.set_strict(False)
        old_signature = request_data['get_data']['Signature']
        request_data['get_data']['Signature'] = 'vfWbbc47PkP3ejx4bjKsRX7lo9Ml1WRoE5J5owF/0mnyKHfSY6XbhO1wwjBV5vWdrUVX+xp6slHyAf4YoAsXFS0qhan6txDiZY4Oec6yE+l10iZbzvie06I4GPak4QrQ4gAyXOSzwCrRmJu4gnpeUxZ6IqKtdrKfAYRAcVf3333='
        response_3 = OneLogin_Saml2_Logout_Response(settings, request_data['get_data']['SAMLResponse'])
        self.assertFalse(response_3.is_valid(request_data))
        self.assertIn('Signature validation failed. Logout Response rejected', response_3.get_error())

        request_data['get_data']['Signature'] = old_signature
        old_signature_algorithm = request_data['get_data']['SigAlg']
        del request_data['get_data']['SigAlg']
        response_4 = OneLogin_Saml2_Logout_Response(settings, request_data['get_data']['SAMLResponse'])
        self.assertTrue(response_4.is_valid(request_data))

        request_data['get_data']['RelayState'] = 'http://example.com/relaystate'
        response_5 = OneLogin_Saml2_Logout_Response(settings, request_data['get_data']['SAMLResponse'])
        self.assertFalse(response_5.is_valid(request_data))
        self.assertIn('Signature validation failed. Logout Response rejected', response_5.get_error())

        settings.set_strict(True)
        current_url = OneLogin_Saml2_Utils.get_self_url_no_query(request_data)
        plain_message_6 = OneLogin_Saml2_Utils.decode_base64_and_inflate(request_data['get_data']['SAMLResponse'])
        plain_message_6 = plain_message_6.replace('https://pitbulk.no-ip.org/newonelogin/demo1/index.php?sls', current_url)
        plain_message_6 = plain_message_6.replace('https://pitbulk.no-ip.org/simplesaml/saml2/idp/metadata.php', 'http://idp.example.com/')
        request_data['get_data']['SAMLResponse'] = OneLogin_Saml2_Utils.deflate_and_base64_encode(plain_message_6)

        response_6 = OneLogin_Saml2_Logout_Response(settings, request_data['get_data']['SAMLResponse'])
        self.assertFalse(response_6.is_valid(request_data))
        self.assertIn('Signature validation failed. Logout Response rejected', response_6.get_error())

        settings.set_strict(False)
        response_7 = OneLogin_Saml2_Logout_Response(settings, request_data['get_data']['SAMLResponse'])
        self.assertFalse(response_7.is_valid(request_data))
        self.assertIn('Signature validation failed. Logout Response rejected', response_7.get_error())

        request_data['get_data']['SigAlg'] = 'http://www.w3.org/2000/09/xmldsig#dsa-sha1'
        response_8 = OneLogin_Saml2_Logout_Response(settings, request_data['get_data']['SAMLResponse'])
        self.assertFalse(response_8.is_valid(request_data))
        self.assertIn('Signature validation failed. Logout Response rejected', response_8.get_error())

        settings_info = self.loadSettingsJSON()
        settings_info['strict'] = True
        settings_info['security']['wantMessagesSigned'] = True
        settings = OneLogin_Saml2_Settings(settings_info)

        request_data['get_data']['SigAlg'] = old_signature_algorithm
        old_signature = request_data['get_data']['Signature']
        del request_data['get_data']['Signature']
        request_data['get_data']['SAMLResponse'] = OneLogin_Saml2_Utils.deflate_and_base64_encode(plain_message_6)
        response_9 = OneLogin_Saml2_Logout_Response(settings, request_data['get_data']['SAMLResponse'])
        self.assertFalse(response_9.is_valid(request_data))
        self.assertIn('The Message of the Logout Response is not signed and the SP require it', response_9.get_error())

        request_data['get_data']['Signature'] = old_signature
        settings_info['idp']['certFingerprint'] = 'afe71c28ef740bc87425be13a2263d37971da1f9'
        del settings_info['idp']['x509cert']
        settings_2 = OneLogin_Saml2_Settings(settings_info)

        response_10 = OneLogin_Saml2_Logout_Response(settings_2, request_data['get_data']['SAMLResponse'])
        self.assertFalse(response_10.is_valid(request_data))
        self.assertIn('In order to validate the sign on the Logout Response, the x509cert of the IdP is required', response_10.get_error())
예제 #54
0
    def testCreateRequestAuthContext(self):
        """
        Tests the OneLogin_Saml2_Authn_Request Constructor.
        The creation of a deflated SAML Request with defined AuthContext
        """
        saml_settings = self.loadSettingsJSON()
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(
            OneLogin_Saml2_Utils.decode_base64_and_inflate(
                authn_request_encoded))
        self.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertIn(OneLogin_Saml2_Constants.AC_PASSWORD, inflated)
        self.assertNotIn(OneLogin_Saml2_Constants.AC_X509, inflated)

        saml_settings['security']['requestedAuthnContext'] = True
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(
            OneLogin_Saml2_Utils.decode_base64_and_inflate(
                authn_request_encoded))
        self.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertIn(OneLogin_Saml2_Constants.AC_PASSWORD_PROTECTED, inflated)
        self.assertNotIn(OneLogin_Saml2_Constants.AC_X509, inflated)

        del saml_settings['security']['requestedAuthnContext']
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(
            OneLogin_Saml2_Utils.decode_base64_and_inflate(
                authn_request_encoded))
        self.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertIn(OneLogin_Saml2_Constants.AC_PASSWORD_PROTECTED, inflated)
        self.assertNotIn(OneLogin_Saml2_Constants.AC_X509, inflated)

        saml_settings['security']['requestedAuthnContext'] = False
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(
            OneLogin_Saml2_Utils.decode_base64_and_inflate(
                authn_request_encoded))
        self.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertNotIn(OneLogin_Saml2_Constants.AC_PASSWORD_PROTECTED,
                         inflated)
        self.assertNotIn(OneLogin_Saml2_Constants.AC_X509, inflated)

        saml_settings['security']['requestedAuthnContext'] = (
            OneLogin_Saml2_Constants.AC_PASSWORD_PROTECTED,
            OneLogin_Saml2_Constants.AC_X509)
        settings = OneLogin_Saml2_Settings(saml_settings)
        authn_request = OneLogin_Saml2_Authn_Request(settings)
        authn_request_encoded = authn_request.get_request()
        inflated = compat.to_string(
            OneLogin_Saml2_Utils.decode_base64_and_inflate(
                authn_request_encoded))
        self.assertRegexpMatches(inflated, '^<samlp:AuthnRequest')
        self.assertIn(OneLogin_Saml2_Constants.AC_PASSWORD_PROTECTED, inflated)
        self.assertIn(OneLogin_Saml2_Constants.AC_X509, inflated)
예제 #55
0
    def __init__(self, settings, request=None, name_id=None, session_index=None, nq=None, name_id_format=None, spnq=None):
        """
        Constructs the Logout Request object.

        :param settings: Setting data
        :type settings: OneLogin_Saml2_Settings

        :param request: Optional. A LogoutRequest to be loaded instead build one.
        :type request: string

        :param name_id: The NameID that will be set in the LogoutRequest.
        :type name_id: string

        :param session_index: SessionIndex that identifies the session of the user.
        :type session_index: string

        :param nq: IDP Name Qualifier
        :type: string

        :param name_id_format: The NameID Format that will be set in the LogoutRequest.
        :type: string

        :param spnq: SP Name Qualifier
        :type: string
        """
        self.__settings = settings
        self.__error = None
        self.id = None

        if request is None:
            sp_data = self.__settings.get_sp_data()
            idp_data = self.__settings.get_idp_data()
            security = self.__settings.get_security_data()

            uid = OneLogin_Saml2_Utils.generate_unique_id()
            self.id = uid

            issue_instant = OneLogin_Saml2_Utils.parse_time_to_SAML(OneLogin_Saml2_Utils.now())

            cert = None
            if security['nameIdEncrypted']:
                exists_multix509enc = 'x509certMulti' in idp_data and \
                    'encryption' in idp_data['x509certMulti'] and \
                    idp_data['x509certMulti']['encryption']
                if exists_multix509enc:
                    cert = idp_data['x509certMulti']['encryption'][0]
                else:
                    cert = idp_data['x509cert']

            if name_id is not None:
                if not name_id_format and sp_data['NameIDFormat'] != OneLogin_Saml2_Constants.NAMEID_UNSPECIFIED:
                    name_id_format = sp_data['NameIDFormat']
            else:
                name_id = idp_data['entityId']
                name_id_format = OneLogin_Saml2_Constants.NAMEID_ENTITY

            # From saml-core-2.0-os 8.3.6, when the entity Format is used:
            # "The NameQualifier, SPNameQualifier, and SPProvidedID attributes
            # MUST be omitted.
            if name_id_format and name_id_format == OneLogin_Saml2_Constants.NAMEID_ENTITY:
                nq = None
                spnq = None

            # NameID Format UNSPECIFIED omitted
            if name_id_format and name_id_format == OneLogin_Saml2_Constants.NAMEID_UNSPECIFIED:
                name_id_format = None

            name_id_obj = OneLogin_Saml2_Utils.generate_name_id(
                name_id,
                spnq,
                name_id_format,
                cert,
                False,
                nq
            )

            if session_index:
                session_index_str = '<samlp:SessionIndex>%s</samlp:SessionIndex>' % session_index
            else:
                session_index_str = ''

            logout_request = OneLogin_Saml2_Templates.LOGOUT_REQUEST % \
                {
                    'id': uid,
                    'issue_instant': issue_instant,
                    'single_logout_url': idp_data['singleLogoutService']['url'],
                    'entity_id': sp_data['entityId'],
                    'name_id': name_id_obj,
                    'session_index': session_index_str,
                }
        else:
            logout_request = OneLogin_Saml2_Utils.decode_base64_and_inflate(request, ignore_zip=True)
            self.id = self.get_id(logout_request)

        self.__logout_request = compat.to_string(logout_request)
예제 #56
0
    def test_full_login_process(self):
        """Asserts the nominal login process works."""
        sso_location = "http://testserver/account/saml/local-accepting-idp/sso/"
        entity_descriptor_list = [
            generate_idp_metadata(
                entity_id=sso_location,
                sso_location=sso_location,
                ui_info_display_names=format_mdui_display_name(
                    "Local accepting IdP"),
            ),
        ]

        # 1/ Select Idp in the provider list
        with mock.patch("urllib.request.urlopen") as urlopen_mock:

            class UrlOpenMock:
                """Mockin object for the urlopen"""
                def read(self):
                    """Allow object to be read several times."""
                    return generate_idp_federation_metadata(
                        entity_descriptor_list=entity_descriptor_list,
                    ).encode("utf-8")

            urlopen_mock.return_value = UrlOpenMock()

            response = self.client.get(
                reverse("account:saml_fer_idp_choice"), )

            self.assertContains(
                response,
                f'action="{reverse("account:social:begin", args=("saml_fer",))}"',
            )
            self.assertContains(response, "local-accepting-idp")

            response = self.client.get(
                f'{reverse("account:social:begin", args=("saml_fer",))}?idp=local-accepting-idp',
            )

            self.assertEqual(response.status_code, 302)
            self.assertTrue(response["Location"].startswith(
                "http://testserver/account/saml/local-accepting-idp/sso/?SAMLRequest="
            ))

            # 2/ Fake the redirection to the SSO
            response = self.client.get(
                f'{reverse("account:social:begin", args=("saml_fer",))}?idp=local-accepting-idp',
                follow=False,
            )

            # 3/ Generate SAML response using SAML request
            query_values = parse_qs(urlparse(response["Location"]).query)
            saml_request = query_values["SAMLRequest"]
            saml_relay_state = query_values["RelayState"]
            readable_saml_request = OneLogin_Saml2_Utils.decode_base64_and_inflate(
                saml_request, )
            saml_request = OneLogin_Saml2_XML.to_etree(readable_saml_request)
            saml_acs_url = saml_request.get("AssertionConsumerServiceURL")
            request_id = saml_request.get("ID")

            auth_response = OneLogin_Saml2_Utils.b64encode(
                generate_auth_response(
                    request_id,
                    saml_acs_url,
                    issuer=
                    "http://testserver/account/saml/local-accepting-idp/sso/",
                ))

            # 4/ POST the data to our endpoint
            response = self.client.post(
                saml_acs_url,
                data={
                    "RelayState": saml_relay_state,
                    "SAMLResponse": auth_response,
                },
            )
            self.assertEqual(response.status_code, 302)
            self.assertEqual(response["Location"], "/")

        # Assert the user is authenticated
        user = auth_get_user(self.client)
        self.assertTrue(user.is_authenticated)

        # Assert the user has an organization
        organization_access = user.organization_accesses.select_related(
            "organization").get()  # also assert there is only one organization
        self.assertEqual(organization_access.role, STUDENT)
        self.assertEqual(organization_access.organization.name,
                         "OrganizationDName")
예제 #57
0
파일: auth.py 프로젝트: rskumar/python-saml
    def process_slo(self,
                    keep_local_session=False,
                    request_id=None,
                    delete_session_cb=None):
        """
        Process the SAML Logout Response / Logout Request sent by the IdP.

        :param keep_local_session: When false will destroy the local session, otherwise will destroy it
        :type keep_local_session: bool

        :param request_id: The ID of the LogoutRequest sent by this SP to the IdP
        :type request_id: string

        :returns: Redirection url
        """
        self.__errors = []

        if 'get_data' in self.__request_data and 'SAMLResponse' in self.__request_data[
                'get_data']:
            logout_response = OneLogin_Saml2_Logout_Response(
                self.__settings,
                self.__request_data['get_data']['SAMLResponse'])
            if not logout_response.is_valid(self.__request_data, request_id):
                self.__errors.append('invalid_logout_response')
                self.__error_reason = logout_response.get_error()
            elif logout_response.get_status(
            ) != OneLogin_Saml2_Constants.STATUS_SUCCESS:
                self.__errors.append('logout_not_success')
            elif not keep_local_session:
                OneLogin_Saml2_Utils.delete_local_session(delete_session_cb)

        elif 'get_data' in self.__request_data and 'SAMLRequest' in self.__request_data[
                'get_data']:
            logout_request = OneLogin_Saml2_Logout_Request(
                self.__settings,
                self.__request_data['get_data']['SAMLRequest'])
            if not logout_request.is_valid(self.__request_data):
                self.__errors.append('invalid_logout_request')
                self.__error_reason = logout_request.get_error()
            else:
                if not keep_local_session:
                    OneLogin_Saml2_Utils.delete_local_session(
                        delete_session_cb)

                in_response_to = OneLogin_Saml2_Logout_Request.get_id(
                    OneLogin_Saml2_Utils.decode_base64_and_inflate(
                        self.__request_data['get_data']['SAMLRequest']))
                response_builder = OneLogin_Saml2_Logout_Response(
                    self.__settings)
                response_builder.build(in_response_to)
                logout_response = response_builder.get_response()

                parameters = {'SAMLResponse': logout_response}
                if 'RelayState' in self.__request_data['get_data']:
                    parameters['RelayState'] = self.__request_data['get_data'][
                        'RelayState']

                security = self.__settings.get_security_data()
                if 'logoutResponseSigned' in security and security[
                        'logoutResponseSigned']:
                    parameters['SigAlg'] = OneLogin_Saml2_Constants.RSA_SHA1
                    parameters['Signature'] = self.build_response_signature(
                        logout_response, parameters.get('RelayState', None))

                return self.redirect_to(self.get_slo_url(), parameters)
        else:
            self.__errors.append('invalid_binding')
            raise OneLogin_Saml2_Error(
                'SAML LogoutRequest/LogoutResponse not found. Only supported HTTP_REDIRECT Binding',
                OneLogin_Saml2_Error.SAML_LOGOUTMESSAGE_NOT_FOUND)
예제 #58
0
    def processResponse(self, chkTime=True, checkInResponseTo=True):

        try:
            # get response and Relay state
            responsePost = self.get_argument('SAMLResponse')
            srelayPost = self.get_argument('RelayState')

            # decode saml response
            #response = responsePost
            self.response = responsePost
            try:
                self.response = OneLogin_Saml2_Utils.decode_base64_and_inflate(
                    responsePost)
            except Exception:
                try:
                    self.response = OneLogin_Saml2_Utils.b64decode(
                        responsePost)
                except Exception:
                    pass

            # try:
            #     #response = OneLogin_Saml2_Utils.b64decode(responsePost)
            #     self.response = OneLogin_Saml2_Utils.b64decode(responsePost)
            # except Exception:
            #     pass

            ## parse XML and make some check
            ns = {
                'md0': OneLogin_Saml2_Constants.NS_SAMLP,
                'md1': OneLogin_Saml2_Constants.NS_SAML
            }
            parsedResponse = xml.etree.ElementTree.fromstring(self.response)

            self.inResponseTo = parsedResponse.get('InResponseTo')
            self.ResponseID = parsedResponse.get('ID')
            issuer = self.issuer = parsedResponse.find("md1:Issuer", ns)
            if issuer is None:
                response_obj = ResponseObj(httpcode=401)
                response_obj.setError('easyspid118')
                return response_obj

            #spByInResponseTo = None
            # try to get sp searching a corresponding request and raise error if checkInResponseTo is True
            # inResponseChk = waitFuture(asyncio.run_coroutine_threadsafe(self.dbobjSaml.execute_statment("chk_idAssertion('%s')" %
            #             inResponseTo), globalsObj.ioloop))
            # if inResponseChk['error'] == 0 and inResponseChk['result'] is not None:
            #         spByInResponseTo = inResponseChk['result'][0]['cod_sp']
            #
            # elif checkInResponseTo and inResponseChk['error'] == 0 and inResponseChk['result'] == None:
            #     response_obj = ResponseObj(httpcode=404, ID = ResponseID)
            #     response_obj.setError('easyspid120')
            #     response_obj.setResult(response = str(response, 'utf-8'))
            #     return response_obj
            #
            # elif inResponseChk['error'] > 0:
            #     response_obj = ResponseObj(httpcode=500)
            #     response_obj.setError('easyspid105')
            #     response_obj.setResult(inResponseChk['result'])
            #     return response_obj

            # try to get sp searching a corresponding request and raise error if checkInResponseTo is True
            spByInResponseTo = self.chkExistsReq(checkInResponseTo)

            ### check StatusCode to find errors
            firstChk = easyspid.lib.utils.validateAssertion(
                str(self.response, 'utf-8'), None, None)
            if not firstChk['chkStatus']:
                #get errors codes
                samlErrors = waitFuture(
                    asyncio.run_coroutine_threadsafe(
                        getResponseError(parsedResponse,
                                         sp=spByInResponseTo,
                                         namespace=ns), globalsObj.ioloop))

                if samlErrors['error'] == '0':
                    response_obj = ResponseObj(httpcode=400,
                                               ID=self.ResponseID)
                    response_obj.setError('easyspid121')
                    response_obj.setResult(response=str(
                        self.response, 'utf-8'),
                                           format='json',
                                           samlErrors=samlErrors['status'])

                    return self.formatError(response_obj, srelayPost,
                                            samlErrors['service'])

                elif samlErrors['error'] == 'easyspid114':
                    response_obj = ResponseObj(httpcode=404)
                    response_obj.setError('easyspid114')
                    return response_obj

                else:
                    response_obj = ResponseObj(httpcode=500)
                    response_obj.setError('500')
                    response_obj.setResult(samlErrors['error'])
                    return response_obj

            #decode Relay state
            #srelay = srelayPost
            self.srelay = srelayPost
            try:
                self.srelay = OneLogin_Saml2_Utils.decode_base64_and_inflate(
                    srelayPost)
            except Exception:
                try:
                    self.srelay = OneLogin_Saml2_Utils.b64decode(srelayPost)

                except Exception:
                    pass

                #self.srelay = OneLogin_Saml2_Utils.b64decode(srelayPost)
                #pass
            # try:
            #      #srelay = OneLogin_Saml2_Utils.b64decode(srelayPost)
            #      self.srelay = OneLogin_Saml2_Utils.b64decode(srelayPost)
            # except Exception:
            #      pass

            ## get sp by ID
            #ns = {'md0': OneLogin_Saml2_Constants.NS_SAMLP, 'md1': OneLogin_Saml2_Constants.NS_SAML}
            #parsedResponse = xml.etree.ElementTree.fromstring(response)
            #issuer = self.issuer = parsedResponse.find("md1:Issuer", ns)
            #inResponseTo = parsedResponse.get('InResponseTo')

            #get audience
            audience = self.audience = parsedResponse.find(
                'md1:Assertion/md1:Conditions/md1:AudienceRestriction/md1:Audience',
                ns)
            if audience is None:
                response_obj = ResponseObj(httpcode=401)
                response_obj.setError('easyspid118')
                return response_obj

            # if issuer is None or audience is None:
            #     response_obj = ResponseObj(httpcode=401)
            #     response_obj.setError('easyspid118')
            #     return response_obj

            #task1 = asyncio.run_coroutine_threadsafe(self.dbobjSaml.execute_statment("chk_idAssertion('%s')" %
            #        inResponseTo), globalsObj.ioloop)
            # task2 = asyncio.run_coroutine_threadsafe(self.dbobjSaml.execute_statment("get_provider_byentityid(%s, '%s')" %
            #         ('True', '{'+(self.issuer.text.strip())+'}')),  globalsObj.ioloop)
            #task3 = asyncio.run_coroutine_threadsafe(self.dbobjSaml.execute_statment("get_provider_byentityid(%s, '%s')" %
            #       ('True', '{'+(audience.text.strip())+'}')),  globalsObj.ioloop)

            #assert not task1.done()
            #inResponseChk = task1.result()
            #inResponseChk = waitFuture(task1)
            #audienceChk = waitFuture(task3)
            #spByAudience = None
            #spByInResponseTo = None

            #if inResponseChk['error'] == 0 and inResponseChk['result'] is not None:
            #    spByInResponseTo = inResponseChk['result'][0]['cod_sp']

            # if audienceChk['error'] == 0 and audienceChk['result'] is not None:
            #     spByAudience = audienceChk['result'][0]['cod_provider']

            #check audinece
            # if spByAudience is None:
            #     response_obj = ResponseObj(httpcode=404)
            #     response_obj.setError('easyspid115')
            #     return response_obj

            # get sp by audience
            spByAudience = self.getSpByAudience()

            #check inresponseTo and spByAudience == spByInResponseTo
            if checkInResponseTo and spByAudience == spByInResponseTo:
                sp = spByAudience

            elif checkInResponseTo and spByAudience != spByInResponseTo:
                response_obj = ResponseObj(httpcode=401)
                response_obj.setError('easyspid110')
                return response_obj

            sp = spByAudience

            # get service by sp and relay_state
            try:
                task = asyncio.run_coroutine_threadsafe(
                    self.dbobjSaml.execute_statment(
                        "get_service(%s, '%s', '%s')" %
                        ('True', str(self.srelay), sp)), globalsObj.ioloop)
                #assert not task.done()
                #service = task.result()
                service = waitFuture(task)

                if service['error'] == 0 and service['result'] is not None:
                    # costruisci il routing
                    self.routing = dict()
                    self.routing['url'] = service['result'][0]['url']
                    self.routing['relaystate'] = self.srelay
                    self.routing['format'] = service['result'][0]['format']

                elif service['error'] > 0 or service['result'] is None:
                    response_obj = ResponseObj(httpcode=500,
                                               debugMessage=service['result'])
                    response_obj.setError("easyspid111")
                    return response_obj

            except Exception:
                pass

            # get IdP
            # idpEntityId = waitFuture(task2)
            #
            # if idpEntityId['error'] == 0 and idpEntityId['result'] is not None:
            #     idp_metadata = idpEntityId['result'][0]['xml']
            #     idp = idpEntityId['result'][0]['cod_provider']
            #
            # elif idpEntityId['error'] == 0 and idpEntityId['result'] is None:
            #     response_obj = ResponseObj(httpcode=404)
            #     response_obj.setError('easyspid103')
            #     return response_obj
            #
            # elif idpEntityId['error'] > 0:
            #     response_obj = ResponseObj(httpcode=500, debugMessage=idpEntityId['result'])
            #     response_obj.setError("easyspid105")
            #     return response_obj

            # get IdP and metadata
            (idp_metadata, idp) = self.getIdentyIdp()

            # get sp settings
            task = asyncio.run_coroutine_threadsafe(
                easyspid.lib.easyspid.spSettings(sp, idp, close=True),
                globalsObj.ioloop)
            sp_settings = waitFuture(task)

            if sp_settings['error'] == 0 and sp_settings['result'] != None:

                ## insert response into DB
                task = asyncio.run_coroutine_threadsafe(
                    self.dbobjSaml.execute_statment(
                        "write_assertion('%s', '%s', '%s', '%s')" %
                        (str(self.response, 'utf-8').replace(
                            "'", "''"), sp, idp, self.remote_ip)),
                    globalsObj.ioloop)
                wrtAuthn = waitFuture(task)

                if wrtAuthn['error'] == 0:

                    if self.routing['format'] == 'saml':
                        return self.passthrough()

                    task = asyncio.run_coroutine_threadsafe(
                        self.dbobjJwt.execute_statment(
                            "get_token_by_cod('%s')" %
                            (wrtAuthn['result'][0]['cod_token'])),
                        globalsObj.ioloop)
                    #assert not task.done()
                    #jwt = task.result()
                    jwt = waitFuture(task)

                else:
                    response_obj = ResponseObj(httpcode=500,
                                               debugMessage=wrtAuthn['result'])
                    response_obj.setError("easyspid105")
                    logging.getLogger(
                        type(self).__module__ + "." +
                        type(self).__qualname__).error('Exception',
                                                       exc_info=True)
                    return response_obj

                # create settings OneLogin dict
                #settings = sp_settings['result']
                prvdSettings = Saml2_Settings(sp_settings['result'])

                chk = easyspid.lib.utils.validateAssertion(
                    str(self.response, 'utf-8'),
                    sp_settings['result']['idp']['x509cert_fingerprint'],
                    sp_settings['result']['idp']['x509cert_fingerprintalg'])

                chk['issuer'] = issuer.text.strip()
                chk['audience'] = audience.text.strip()

                if not chk['chkStatus']:
                    response_obj = ResponseObj(httpcode=401)
                    response_obj.setError('easyspid107')
                    return response_obj

                elif not chk['schemaValidate']:
                    response_obj = ResponseObj(httpcode=401)
                    response_obj.setError('easyspid104')
                    response_obj.setResult(responseValidate=chk)
                    return response_obj

                elif not chk['signCheck']:
                    response_obj = ResponseObj(httpcode=401)
                    response_obj.setError('easyspid106')
                    response_obj.setResult(responseValidate=chk)
                    return response_obj

                elif not chk[
                        'certAllowed'] and globalsObj.easyspid_checkCertificateAllowed:
                    response_obj = ResponseObj(httpcode=401)
                    response_obj.setError('easyspid116')
                    response_obj.setResult(responseValidate=chk)
                    return response_obj

                elif not chk[
                        'certValidity'] and globalsObj.easyspid_checkCertificateValidity:
                    response_obj = ResponseObj(httpcode=401)
                    response_obj.setError('easyspid117')
                    response_obj.setResult(responseValidate=chk)
                    return response_obj

                elif chkTime and not chk['chkTime']:
                    response_obj = ResponseObj(httpcode=401)
                    response_obj.setError('easyspid108')
                    return response_obj

                #get all attributes
                attributes = chk['serviceAttributes']
                attributes_tmp = dict()
                for key in attributes:
                    attributes_tmp[key] = attributes[key][0]
                attributes = attributes_tmp

                # build response form
                try:
                    with open(
                            os.path.join(globalsObj.modules_basedir,
                                         globalsObj.easyspid_responseFormPath),
                            'rb') as myfile:
                        response_form = myfile.read().decode("utf-8")
                except:
                    with open(globalsObj.easyspid_responseFormPath,
                              'rb') as myfile:
                        response_form = myfile.read().decode("utf-8")

                response_obj = ResponseObj(
                    httpcode=200, ID=wrtAuthn['result'][0]['ID_assertion'])
                response_obj.setError('200')
                response_obj.setResult(attributes=attributes,
                                       jwt=jwt['result'][0]['token'],
                                       responseValidate=chk,
                                       response=str(self.response, 'utf-8'),
                                       format='json')

                response_form = response_form.replace("%URLTARGET%",
                                                      self.routing['url'])
                response_form = response_form.replace("%RELAYSTATE%",
                                                      srelayPost)
                response_form = response_form.replace(
                    "%RESPONSE%",
                    OneLogin_Saml2_Utils.b64encode(response_obj.jsonWrite()))
                self.postTo = response_form

            elif sp_settings['error'] == 0 and sp_settings['result'] == None:
                response_obj = ResponseObj(httpcode=404)
                response_obj.setError('easyspid114')

            elif sp_settings['error'] > 0:
                #response_obj = sp_settings['result']
                response_obj = sp_settings

        except goExit as e:
            return e.expression

        except tornado.web.MissingArgumentError as error:
            response_obj = ResponseObj(debugMessage=error.log_message,
                                       httpcode=error.status_code,
                                       devMessage=error.log_message)
            response_obj.setError(str(error.status_code))
            logging.getLogger(
                type(self).__module__ + "." + type(self).__qualname__).error(
                    '%s' % error, exc_info=True)

        except Exception as inst:
            response_obj = ResponseObj(httpcode=500)
            response_obj.setError('500')
            logging.getLogger(
                type(self).__module__ + "." + type(self).__qualname__).error(
                    'Exception', exc_info=True)

        return response_obj