summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Kanakarakis <ivan.kanak@gmail.com>2019-05-29 19:10:53 +0300
committerGitHub <noreply@github.com>2019-05-29 19:10:53 +0300
commit1cc23fd3b93d82bd557a8595fdb1aac91f204c66 (patch)
tree74cc30cb94df411bb9e0d49733ede6fe4740a8d0
parent73215f6b8a4095c4e74de2faae5f22b80fcb64d5 (diff)
parent477c4405575ab7ab5650743d73c9709a589f23b7 (diff)
downloadpysaml2-1cc23fd3b93d82bd557a8595fdb1aac91f204c66.tar.gz
Merge pull request #618 from abliqo/holder-of-key
Fix parsing of assertions with Holder-of-Key profile
-rw-r--r--.gitignore3
-rw-r--r--src/saml2/response.py4
-rw-r--r--tests/saml2_data.py30
-rw-r--r--tests/saml_hok.xml45
-rw-r--r--tests/saml_hok_invalid.xml30
-rw-r--r--tests/test_02_saml.py56
-rw-r--r--tests/test_93_hok.py93
7 files changed, 244 insertions, 17 deletions
diff --git a/.gitignore b/.gitignore
index a1e06506..7db203ec 100644
--- a/.gitignore
+++ b/.gitignore
@@ -114,6 +114,9 @@ venv.bak/
# Rope project settings
.ropeproject
+# Visual Studio Code files
+.vscode/
+
# mkdocs documentation
/site
diff --git a/src/saml2/response.py b/src/saml2/response.py
index 2660e738..4c884c30 100644
--- a/src/saml2/response.py
+++ b/src/saml2/response.py
@@ -722,11 +722,11 @@ class AuthnResponse(StatusResponse):
return True
def _holder_of_key_confirmed(self, data):
- if not data:
+ if not data or not data.extension_elements:
return False
has_keyinfo = False
- for element in extension_elements_to_elements(data,
+ for element in extension_elements_to_elements(data.extension_elements,
[samlp, saml, xenc, ds]):
if isinstance(element, ds.KeyInfo):
has_keyinfo = True
diff --git a/tests/saml2_data.py b/tests/saml2_data.py
index fe650e7b..f81f2ce5 100644
--- a/tests/saml2_data.py
+++ b/tests/saml2_data.py
@@ -123,6 +123,36 @@ TEST_SUBJECT_CONFIRMATION = """<?xml version="1.0" encoding="utf-8"?>
</SubjectConfirmation>
"""
+TEST_HOLDER_OF_KEY_SUBJECT_CONFIRMATION = """<?xml version="1.0" encoding="utf-8"?>
+<SubjectConfirmation
+ Method="urn:oasis:names:tc:SAML:2.0:cm:holder-of-key"
+ xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
+ <SubjectConfirmationData
+ InResponseTo="responseID"
+ NotOnOrAfter="2007-09-14T01:05:02Z"
+ Recipient="recipient">
+ <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <X509Data xmlns="http://www.w3.org/2000/09/xmldsig#">
+ <X509Certificate xmlns="http://www.w3.org/2000/09/xmldsig#">
+MIICITCCAYoCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNV
+BAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwF
+Wnp6enoxDTALBgNVBAMMBHRlc3QwIBcNMTkwNDEyMTk1MDM0WhgPMzAxODA4MTMx
+OTUwMzRaMFgxCzAJBgNVBAYTAnp6MQswCQYDVQQIDAJ6ejENMAsGA1UEBwwEenp6
+ejEOMAwGA1UECgwFWnp6enoxDjAMBgNVBAsMBVp6enp6MQ0wCwYDVQQDDAR0ZXN0
+MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHcj80WU/XBsd9FlyQmfjPUdfm
+edhCFDd6TEQmZNNqP/UG+VkGa+BXjRIHMfic/WxPTbGhCjv68ci0UDNomUXagFex
+LGNpkwa7+CRVtoc/1xgq+ySE6M4nhcCutScoxNvWNn5eSQ66i3U0sTv91MgsXxqE
+dTaiZg0BIufEc3dueQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAGUV5B+USHvaRa8k
+gCNJSuNpo6ARlv0ekrk8bbdNRBiEUdCMyoGJFfuM9K0zybX6Vr25wai3nvaog294
+Vx/jWjX2g5SDbjItH6VGy6C9GCGf1A07VxFRCfJn5tA9HuJjPKiE+g/BmrV5N4Ce
+alzFxPHWYkNOzoRU8qI7OqUai1kL
+ </X509Certificate>
+ </X509Data>
+ </KeyInfo>
+ </SubjectConfirmationData>
+</SubjectConfirmation>
+"""
+
TEST_SUBJECT = """<?xml version="1.0" encoding="utf-8"?>
<Subject xmlns="urn:oasis:names:tc:SAML:2.0:assertion">
<NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
diff --git a/tests/saml_hok.xml b/tests/saml_hok.xml
new file mode 100644
index 00000000..6aad625a
--- /dev/null
+++ b/tests/saml_hok.xml
@@ -0,0 +1,45 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- SAML response with multiple 'holder-of-key' subject confirmations. -->
+<ns0:Response xmlns:ns0="urn:oasis:names:tc:SAML:2.0:protocol"
+ xmlns:ns1="urn:oasis:names:tc:SAML:2.0:assertion"
+ xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Destination="https://sp:443/.auth/saml/login" ID="_df9a1eadc90519252694519504a13dfb8dd67a1bb4" InResponseTo="id-KHlas49TtW2VdC8WN" IssueInstant="2019-05-14T20:35:13Z" Version="2.0">
+ <ns1:Issuer>https://idp:8443</ns1:Issuer>
+ <ns0:Status>
+ <ns0:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
+ </ns0:Status>
+ <ns1:Assertion ID="_12d211a5015f71eba8f837d2aa8b95b28bbdc4599b" IssueInstant="2019-05-14T20:35:13Z" Version="2.0">
+ <ns1:Issuer>https://idp:8443</ns1:Issuer>
+ <ns1:Subject>
+ <ns1:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">57a0a35eefdb29ca8b4ab78d5a118117</ns1:NameID>
+ <ns1:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:holder-of-key">
+ <ns1:SubjectConfirmationData InResponseTo="id-KHlas49TtW2VdC8WN" NotOnOrAfter="2019-05-14T20:36:13Z" Recipient="https://sp:443/.auth/saml/login">
+ <ns2:KeyInfo>
+ <ns2:X509Data>
+ <ns2:X509Certificate>MIICITCCAYoCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNVBAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwFWnp6enoxDTALBgNVBAMMBHRlc3QwIBcNMTkwNDEyMTk1MDM0WhgPMzAxODA4MTMxOTUwMzRaMFgxCzAJBgNVBAYTAnp6MQswCQYDVQQIDAJ6ejENMAsGA1UEBwwEenp6ejEOMAwGA1UECgwFWnp6enoxDjAMBgNVBAsMBVp6enp6MQ0wCwYDVQQDDAR0ZXN0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHcj80WU/XBsd9FlyQmfjPUdfmedhCFDd6TEQmZNNqP/UG+VkGa+BXjRIHMfic/WxPTbGhCjv68ci0UDNomUXagFexLGNpkwa7+CRVtoc/1xgq+ySE6M4nhcCutScoxNvWNn5eSQ66i3U0sTv91MgsXxqEdTaiZg0BIufEc3dueQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAGUV5B+USHvaRa8kgCNJSuNpo6ARlv0ekrk8bbdNRBiEUdCMyoGJFfuM9K0zybX6Vr25wai3nvaog294Vx/jWjX2g5SDbjItH6VGy6C9GCGf1A07VxFRCfJn5tA9HuJjPKiE+g/BmrV5N4CealzFxPHWYkNOzoRU8qI7OqUai1kL</ns2:X509Certificate>
+ </ns2:X509Data>
+ </ns2:KeyInfo>
+ </ns1:SubjectConfirmationData>
+ </ns1:SubjectConfirmation>
+ <ns1:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:holder-of-key">
+ <ns1:SubjectConfirmationData InResponseTo="id-KHlas49TtW2VdC8WN" NotOnOrAfter="2019-05-14T20:36:13Z" Recipient="https://sp:443/.auth/saml/login">
+ <ns2:KeyInfo>
+ <ns2:X509Data>
+ <ns2:X509Certificate>MIICITCCAYoCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNVBAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwFWnp6enoxDTALBgNVBAMMBHRlc3QwIBcNMTkwNDEyMTk1MDM0WhgPMzAxODA4MTMxOTUwMzRaMFgxCzAJBgNVBAYTAnp6MQswCQYDVQQIDAJ6ejENMAsGA1UEBwwEenp6ejEOMAwGA1UECgwFWnp6enoxDjAMBgNVBAsMBVp6enp6MQ0wCwYDVQQDDAR0ZXN0MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjW0kJM+4baWKtvO24ZsGXNvNKKkwTMz7OW5Z6BRqhSOq2WA0c5NCpMk6rD8Z2OTFEolPojEjf8dVyd/Ds/hrjFKQv8wQgbdXLN51YTIsgd6h+hBJO+vzhl0PT4aT7M0JKo5ALtS6qk4tsworW2BnwyvsGSAinwfeWt4t/b1J3kwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAFtj7WArQQBugmh/KQjjlfTQ5A052QeXfgTyO9vv1S6MRIi7qgiaEv49cGXnJv/TWbySkMKObPMUApjg6z8PqcxuShew5FCTkNvwhABFPiyu0fUj3e2FEPHfsBu76jz4ugtmhUqjqhzwFY9ctnWRkkl6J0AjM3LnHOSgjNIclDZG</ns2:X509Certificate>
+ </ns2:X509Data>
+ </ns2:KeyInfo>
+ </ns1:SubjectConfirmationData>
+ </ns1:SubjectConfirmation>
+ </ns1:Subject>
+ <ns1:AuthnStatement AuthnInstant="2019-05-14T20:35:13Z" SessionIndex="1">
+ <ns1:AuthnContext>
+ <ns1:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</ns1:AuthnContextClassRef>
+ </ns1:AuthnContext>
+ </ns1:AuthnStatement>
+ <ns1:AttributeStatement>
+ <ns1:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <ns1:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">testuser</ns1:AttributeValue>
+ </ns1:Attribute>
+ </ns1:AttributeStatement>
+ </ns1:Assertion>
+</ns0:Response>
diff --git a/tests/saml_hok_invalid.xml b/tests/saml_hok_invalid.xml
new file mode 100644
index 00000000..53c9edb9
--- /dev/null
+++ b/tests/saml_hok_invalid.xml
@@ -0,0 +1,30 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<!-- SAML response with invalid 'holder-of-key' SubjectConfirmation: missing KeyInfo element. -->
+<ns0:Response xmlns:ns0="urn:oasis:names:tc:SAML:2.0:protocol"
+ xmlns:ns1="urn:oasis:names:tc:SAML:2.0:assertion"
+ xmlns:ns2="http://www.w3.org/2000/09/xmldsig#"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" Destination="https://sp:443/.auth/saml/login" ID="_df9a1eadc90519252694519504a13dfb8dd67a1bb4" InResponseTo="id-KHlas49TtW2VdC8WN" IssueInstant="2019-05-14T20:35:13Z" Version="2.0">
+ <ns1:Issuer>https://idp:8443</ns1:Issuer>
+ <ns0:Status>
+ <ns0:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
+ </ns0:Status>
+ <ns1:Assertion ID="_12d211a5015f71eba8f837d2aa8b95b28bbdc4599b" IssueInstant="2019-05-14T20:35:13Z" Version="2.0">
+ <ns1:Issuer>https://idp:8443</ns1:Issuer>
+ <ns1:Subject>
+ <ns1:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">57a0a35eefdb29ca8b4ab78d5a118117</ns1:NameID>
+ <ns1:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:holder-of-key">
+ <ns1:SubjectConfirmationData InResponseTo="id-KHlas49TtW2VdC8WN" NotOnOrAfter="2019-05-14T20:36:13Z" Recipient="https://sp:443/.auth/saml/login" />
+ </ns1:SubjectConfirmation>
+ </ns1:Subject>
+ <ns1:AuthnStatement AuthnInstant="2019-05-14T20:35:13Z" SessionIndex="1">
+ <ns1:AuthnContext>
+ <ns1:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</ns1:AuthnContextClassRef>
+ </ns1:AuthnContext>
+ </ns1:AuthnStatement>
+ <ns1:AttributeStatement>
+ <ns1:Attribute Name="uid" NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri">
+ <ns1:AttributeValue xmlns:xs="http://www.w3.org/2001/XMLSchema" xsi:type="xs:string">testuser</ns1:AttributeValue>
+ </ns1:Attribute>
+ </ns1:AttributeStatement>
+ </ns1:Assertion>
+</ns0:Response>
diff --git a/tests/test_02_saml.py b/tests/test_02_saml.py
index 7ff64885..8ab6ca04 100644
--- a/tests/test_02_saml.py
+++ b/tests/test_02_saml.py
@@ -867,35 +867,61 @@ class TestSubjectConfirmation:
self.sc.subject_confirmation_data = saml.subject_confirmation_data_from_string(
saml2_data.TEST_SUBJECT_CONFIRMATION_DATA)
new_sc = saml.subject_confirmation_from_string(self.sc.to_string())
- assert new_sc.name_id.sp_provided_id == "sp provided id"
- assert new_sc.method == saml.SCM_BEARER
- assert new_sc.subject_confirmation_data.not_before == \
- "2007-08-31T01:05:02Z"
- assert new_sc.subject_confirmation_data.not_on_or_after == \
- "2007-09-14T01:05:02Z"
- assert new_sc.subject_confirmation_data.recipient == "recipient"
- assert new_sc.subject_confirmation_data.in_response_to == "responseID"
- assert new_sc.subject_confirmation_data.address == "127.0.0.1"
-
- def testUsingTestData(self):
- """Test subject_confirmation_from_string() using test data"""
+ self._assertBearer(new_sc)
+ def testBearerUsingTestData(self):
+ """Test subject_confirmation_from_string() using test data for 'bearer' SubjectConfirmation"""
sc = saml.subject_confirmation_from_string(
saml2_data.TEST_SUBJECT_CONFIRMATION)
+ assert sc.verify()
+ self._assertBearer(sc)
+
+ def _assertBearer(self, sc):
+ """Asserts SubjectConfirmation that has method 'bearer'"""
assert sc.name_id.sp_provided_id == "sp provided id"
assert sc.method == saml.SCM_BEARER
+ assert sc.subject_confirmation_data is not None
assert sc.subject_confirmation_data.not_before == "2007-08-31T01:05:02Z"
assert sc.subject_confirmation_data.not_on_or_after == "2007-09-14T01:05:02Z"
assert sc.subject_confirmation_data.recipient == "recipient"
assert sc.subject_confirmation_data.in_response_to == "responseID"
assert sc.subject_confirmation_data.address == "127.0.0.1"
+ key_info = sc.subject_confirmation_data.extensions_as_elements(ds.KeyInfo.c_tag, ds)
+ assert len(key_info) == 0
- def testVerify(self):
- """Test SubjectConfirmation verify"""
+ def testHolderOfKeyUsingTestData(self):
+ """Test subject_confirmation_from_string() using test data for 'holder-of-key' SubjectConfirmation"""
sc = saml.subject_confirmation_from_string(
- saml2_data.TEST_SUBJECT_CONFIRMATION)
+ saml2_data.TEST_HOLDER_OF_KEY_SUBJECT_CONFIRMATION
+ )
assert sc.verify()
+ assert sc.method == saml.SCM_HOLDER_OF_KEY
+ assert sc.subject_confirmation_data is not None
+ assert sc.subject_confirmation_data.not_on_or_after == "2007-09-14T01:05:02Z"
+ assert sc.subject_confirmation_data.recipient == "recipient"
+ assert sc.subject_confirmation_data.in_response_to == "responseID"
+
+ key_info = sc.subject_confirmation_data.extensions_as_elements(ds.KeyInfo.c_tag, ds)
+ assert len(key_info) == 1
+ assert len(key_info[0].x509_data) == 1
+
+ expected_cert = (
+ "MIICITCCAYoCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNV"
+ "BAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwF"
+ "Wnp6enoxDTALBgNVBAMMBHRlc3QwIBcNMTkwNDEyMTk1MDM0WhgPMzAxODA4MTMx"
+ "OTUwMzRaMFgxCzAJBgNVBAYTAnp6MQswCQYDVQQIDAJ6ejENMAsGA1UEBwwEenp6"
+ "ejEOMAwGA1UECgwFWnp6enoxDjAMBgNVBAsMBVp6enp6MQ0wCwYDVQQDDAR0ZXN0"
+ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHcj80WU/XBsd9FlyQmfjPUdfm"
+ "edhCFDd6TEQmZNNqP/UG+VkGa+BXjRIHMfic/WxPTbGhCjv68ci0UDNomUXagFex"
+ "LGNpkwa7+CRVtoc/1xgq+ySE6M4nhcCutScoxNvWNn5eSQ66i3U0sTv91MgsXxqE"
+ "dTaiZg0BIufEc3dueQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAGUV5B+USHvaRa8k"
+ "gCNJSuNpo6ARlv0ekrk8bbdNRBiEUdCMyoGJFfuM9K0zybX6Vr25wai3nvaog294"
+ "Vx/jWjX2g5SDbjItH6VGy6C9GCGf1A07VxFRCfJn5tA9HuJjPKiE+g/BmrV5N4Ce"
+ "alzFxPHWYkNOzoRU8qI7OqUai1kL"
+ )
+ xcert = key_info[0].x509_data[0].x509_certificate
+ assert xcert.text.strip().replace("\n", "") == expected_cert
class TestSubject:
diff --git a/tests/test_93_hok.py b/tests/test_93_hok.py
new file mode 100644
index 00000000..9d74f490
--- /dev/null
+++ b/tests/test_93_hok.py
@@ -0,0 +1,93 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+from pathutils import dotname, full_path
+
+from pytest import raises
+
+from saml2 import xmldsig as ds
+from saml2.config import config_factory
+from saml2.response import VerificationError
+from saml2.response import authn_response
+
+
+HOLDER_OF_KEY_RESPONSE_FILE = full_path("saml_hok.xml")
+INVALID_HOLDER_OF_KEY_RESPONSE_FILE = full_path("saml_hok_invalid.xml")
+
+
+class TestHolderOfKeyResponse:
+ def test_valid_hok_response_is_parsed(self):
+ """Verifies that response with 'holder-of-key' subject confirmations is parsed successfully."""
+ resp = self._get_test_response(HOLDER_OF_KEY_RESPONSE_FILE)
+ resp.do_not_verify = True
+ resp.parse_assertion()
+ assert resp.get_subject() is not None
+ assert len(resp.assertion.subject.subject_confirmation) == 2
+
+ actual_hok_certs = [
+ ki.x509_data[0].x509_certificate.text.strip()
+ for sc in resp.assertion.subject.subject_confirmation
+ for ki in sc.subject_confirmation_data.extensions_as_elements(
+ ds.KeyInfo.c_tag, ds
+ )
+ ]
+ assert actual_hok_certs == self._expected_hok_certs()
+
+ def _expected_hok_certs(self):
+ certs = [
+ (
+ "MIICITCCAYoCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNV"
+ "BAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwF"
+ "Wnp6enoxDTALBgNVBAMMBHRlc3QwIBcNMTkwNDEyMTk1MDM0WhgPMzAxODA4MTMx"
+ "OTUwMzRaMFgxCzAJBgNVBAYTAnp6MQswCQYDVQQIDAJ6ejENMAsGA1UEBwwEenp6"
+ "ejEOMAwGA1UECgwFWnp6enoxDjAMBgNVBAsMBVp6enp6MQ0wCwYDVQQDDAR0ZXN0"
+ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDHcj80WU/XBsd9FlyQmfjPUdfm"
+ "edhCFDd6TEQmZNNqP/UG+VkGa+BXjRIHMfic/WxPTbGhCjv68ci0UDNomUXagFex"
+ "LGNpkwa7+CRVtoc/1xgq+ySE6M4nhcCutScoxNvWNn5eSQ66i3U0sTv91MgsXxqE"
+ "dTaiZg0BIufEc3dueQIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAGUV5B+USHvaRa8k"
+ "gCNJSuNpo6ARlv0ekrk8bbdNRBiEUdCMyoGJFfuM9K0zybX6Vr25wai3nvaog294"
+ "Vx/jWjX2g5SDbjItH6VGy6C9GCGf1A07VxFRCfJn5tA9HuJjPKiE+g/BmrV5N4Ce"
+ "alzFxPHWYkNOzoRU8qI7OqUai1kL"
+ ),
+ (
+ "MIICITCCAYoCAQEwDQYJKoZIhvcNAQELBQAwWDELMAkGA1UEBhMCenoxCzAJBgNV"
+ "BAgMAnp6MQ0wCwYDVQQHDAR6enp6MQ4wDAYDVQQKDAVaenp6ejEOMAwGA1UECwwF"
+ "Wnp6enoxDTALBgNVBAMMBHRlc3QwIBcNMTkwNDEyMTk1MDM0WhgPMzAxODA4MTMx"
+ "OTUwMzRaMFgxCzAJBgNVBAYTAnp6MQswCQYDVQQIDAJ6ejENMAsGA1UEBwwEenp6"
+ "ejEOMAwGA1UECgwFWnp6enoxDjAMBgNVBAsMBVp6enp6MQ0wCwYDVQQDDAR0ZXN0"
+ "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjW0kJM+4baWKtvO24ZsGXNvNK"
+ "KkwTMz7OW5Z6BRqhSOq2WA0c5NCpMk6rD8Z2OTFEolPojEjf8dVyd/Ds/hrjFKQv"
+ "8wQgbdXLN51YTIsgd6h+hBJO+vzhl0PT4aT7M0JKo5ALtS6qk4tsworW2BnwyvsG"
+ "SAinwfeWt4t/b1J3kwIDAQABMA0GCSqGSIb3DQEBCwUAA4GBAFtj7WArQQBugmh/"
+ "KQjjlfTQ5A052QeXfgTyO9vv1S6MRIi7qgiaEv49cGXnJv/TWbySkMKObPMUApjg"
+ "6z8PqcxuShew5FCTkNvwhABFPiyu0fUj3e2FEPHfsBu76jz4ugtmhUqjqhzwFY9c"
+ "tnWRkkl6J0AjM3LnHOSgjNIclDZG"
+ ),
+ ]
+ return certs
+
+ def test_invalid_hok_response_fails_verification(self):
+ """Verifies that response with invalid 'holder-of-key' subject confirmations is parsed successfully."""
+ resp = self._get_test_response(INVALID_HOLDER_OF_KEY_RESPONSE_FILE)
+ resp.do_not_verify = True
+
+ with raises(VerificationError):
+ resp.parse_assertion()
+
+ def _get_test_response(self, path):
+ conf = config_factory("idp", dotname("server_conf"))
+ resp = authn_response(
+ conf,
+ "https://sp:443/.auth/saml/login",
+ asynchop=False,
+ allow_unsolicited=True,
+ )
+ with open(path, "r") as fp:
+ authn_response_xml = fp.read()
+ resp.loads(authn_response_xml, False)
+ return resp
+
+
+if __name__ == "__main__":
+ t = TestHolderOfKeyResponse()
+ t.setup_class()
+ t.test_hok_response_is_parsed()