def test_create_light_response_auth_class_alias(self):
        view = IdentityProviderResponseView()

        with patch.object(IdentityProviderResponseView, 'saml_response', new_callable=PropertyMock) as response_mock:
            view.create_light_response('test-light-response-issuer', sentinel.auth_class_map)

        self.assertSequenceEqual(response_mock.mock_calls,
                                 [call(), call().create_light_response(sentinel.auth_class_map)])
    def test_get_saml_response_relay_state_optional(self):
        with cast(BinaryIO, (DATA_DIR / 'saml_response.xml').open('rb')) as f:
            saml_response_xml = f.read()

        view = IdentityProviderResponseView()
        view.request = self.factory.post(self.url, {'SAMLResponse': b64encode(saml_response_xml).decode('ascii')})
        saml_response = view.get_saml_response(None, None)
        self.assertIsNone(saml_response.relay_state)
    def test_get_saml_response_invalid_signature(self):
        with cast(TextIO, (DATA_DIR / 'signed_response_and_assertion.xml').open('r')) as f:
            tree = parse_xml(f.read())
        remove_extra_xml_whitespace(tree)
        saml_response_encoded = b64encode(dump_xml(tree, pretty_print=False)).decode('ascii')

        view = IdentityProviderResponseView()
        view.request = self.factory.post(self.url, {'SAMLResponse': saml_response_encoded})
        self.assertRaises(SecurityError, view.get_saml_response, None, WRONG_CERT_FILE)
    def test_create_light_response_correct_id_and_issuer(self):
        self.maxDiff = None
        view = IdentityProviderResponseView()
        view.request = self.factory.post(self.url)

        with cast(TextIO, (DATA_DIR / 'saml_response.xml').open('r')) as f:
            view.saml_response = SAMLResponse(parse_xml(f.read()), 'relay123')

        light_response = view.create_light_response('test-light-response-issuer')
        self.assertEqual(light_response.id, 'test-saml-response-id')  # Preserved
        self.assertEqual(light_response.in_response_to_id, 'test-saml-request-id')  # Preserved
        self.assertEqual(light_response.issuer, 'test-light-response-issuer')  # Replaced
    def test_create_light_token(self, uuid_mock: MagicMock):
        view = IdentityProviderResponseView()
        view.request = self.factory.post(self.url)
        light_response_data = LIGHT_RESPONSE_DICT.copy()
        light_response_data['status'] = Status(**light_response_data['status'])
        view.light_response = LightResponse(**light_response_data)

        token, encoded_token = view.create_light_token('test-token-issuer', 'sha256', 'test-secret')
        self.assertEqual(token.id, 'T0uuid4')
        self.assertEqual(token.issuer, 'test-token-issuer')
        self.assertEqual(token.created, datetime(2017, 12, 11, 16, 12, 5))
        self.assertEqual(token.encode('sha256', 'test-secret').decode('ascii'), encoded_token)
        self.assertEqual(uuid_mock.mock_calls, [call()])
    def test_get_saml_response_signed_and_encrypted(self):
        with cast(TextIO, (DATA_DIR / 'nia_test_response.xml').open('r')) as f:
            tree = parse_xml(f.read())
        remove_extra_xml_whitespace(tree)
        saml_response_encoded = b64encode(dump_xml(tree, pretty_print=False)).decode('ascii')
        view = IdentityProviderResponseView()
        view.request = self.factory.post(self.url, {'SAMLResponse': saml_response_encoded, 'RelayState': 'relay123'})
        saml_response = view.get_saml_response(KEY_FILE, NIA_CERT_FILE)
        self.assertEqual(saml_response.relay_state, 'relay123')

        with cast(TextIO, (DATA_DIR / 'nia_test_response_decrypted_verified.xml').open('r')) as f:
            decrypted_verified_xml = f.read()
        self.assertXMLEqual(dump_xml(saml_response.document).decode('utf-8'), decrypted_verified_xml)
    def test_get_saml_response_encrypted(self):
        with cast(BinaryIO, (DATA_DIR / 'saml_response_encrypted.xml').open('rb')) as f:
            saml_response_xml = f.read()

        with cast(TextIO, (DATA_DIR / 'saml_response_decrypted.xml').open('r')) as f2:
            decrypted_saml_response_xml = f2.read()

        view = IdentityProviderResponseView()
        view.request = self.factory.post(self.url, {'SAMLResponse': b64encode(saml_response_xml).decode('ascii'),
                                                    'RelayState': 'relay123'})
        saml_response = view.get_saml_response(KEY_FILE, None)
        self.assertEqual(saml_response.relay_state, 'relay123')
        self.assertXMLEqual(dump_xml(saml_response.document).decode('utf-8'), decrypted_saml_response_xml)
    def test_get_saml_response_signed(self):
        with cast(TextIO, (DATA_DIR / 'signed_response_and_assertion.xml').open('r')) as f:
            tree = parse_xml(f.read())
        remove_extra_xml_whitespace(tree)
        saml_response_encoded = b64encode(dump_xml(tree, pretty_print=False)).decode('ascii')

        view = IdentityProviderResponseView()
        view.request = self.factory.post(self.url, {'SAMLResponse': saml_response_encoded, 'RelayState': 'relay123'})
        saml_response = view.get_saml_response(None, CERT_FILE)
        self.assertEqual(saml_response.relay_state, 'relay123')

        root = Element(Q_NAMES['saml2p:Response'], {'ID': 'id-response'},
                       nsmap={'saml2': EIDAS_NAMESPACES['saml2'], 'saml2p': EIDAS_NAMESPACES['saml2p']})
        assertion = SubElement(root, Q_NAMES['saml2:Assertion'], {'ID': 'id-0uuid4'})
        SubElement(assertion, Q_NAMES['saml2:Issuer']).text = 'Test Issuer'
        self.assertXMLEqual(dump_xml(saml_response.document).decode('utf-8'), dump_xml(root).decode('utf-8'))
    def test_rewrite_name_id_persistent(self):
        light_response_data = LIGHT_RESPONSE_DICT.copy()
        light_response_data['status'] = Status(**light_response_data['status'])
        light_response_data['subject_name_id_format'] = NameIdFormat.PERSISTENT
        view = IdentityProviderResponseView()
        view.light_response = LightResponse(**light_response_data)
        view.auxiliary_data = {'name_id_format': NameIdFormat.PERSISTENT.value}

        view.rewrite_name_id()
        self.assertEqual(view.light_response.subject_name_id_format, NameIdFormat.PERSISTENT)
        self.assertEqual(view.light_response.subject, 'CZ/CZ/ff70c9dd-6a05-4068-aaa2-b57be4f328e9')
    def test_rewrite_name_id_unspecified_to_transient(self, uuid_mock):
        light_response_data = LIGHT_RESPONSE_DICT.copy()
        light_response_data['status'] = Status(**light_response_data['status'])
        light_response_data['subject_name_id_format'] = NameIdFormat.UNSPECIFIED
        view = IdentityProviderResponseView()
        view.light_response = LightResponse(**light_response_data)
        view.auxiliary_data = {'name_id_format': NameIdFormat.TRANSIENT.value}

        view.rewrite_name_id()
        self.assertEqual(view.light_response.subject_name_id_format, NameIdFormat.TRANSIENT)
        self.assertEqual(view.light_response.subject, '0uuid4')
    def test_rewrite_name_id_failure(self):
        light_response_data = FAILED_LIGHT_RESPONSE_DICT.copy()
        light_response_data['status'] = Status(**light_response_data['status'])
        light_response_data['subject_name_id_format'] = NameIdFormat.PERSISTENT
        view = IdentityProviderResponseView()
        view.light_response = LightResponse(**light_response_data)
        view.auxiliary_data = {'name_id_format': NameIdFormat.TRANSIENT.value}

        view.rewrite_name_id()
        self.assertEqual(view.light_response.subject_name_id_format, NameIdFormat.PERSISTENT)
        self.assertIsNone(view.light_response.subject)
 def test_get_saml_response_no_data(self):
     view = IdentityProviderResponseView()
     view.request = self.factory.post(self.url)
     self.assertRaises(ParseError, view.get_saml_response, None, None)