@@ -62,31 +62,31 @@ def setup_class(self):
62
62
self .conf = config_factory ("sp" , dotname ("server_conf" ))
63
63
self .conf .only_use_keys_in_metadata = False
64
64
self .ar = authn_response (self .conf , "http://lingon.catalogix.se:8087/" )
65
-
65
+
66
66
def test_verify_1 (self ):
67
67
xml_response = "%s" % (self ._resp_ ,)
68
68
print (xml_response )
69
69
self .ar .outstanding_queries = {"id12" : "http://localhost:8088/sso" }
70
70
self .ar .timeslack = 10000
71
71
self .ar .loads (xml_response , decode = False )
72
72
self .ar .verify ()
73
-
73
+
74
74
print (self .ar .__dict__ )
75
75
assert self .ar .came_from == 'http://localhost:8088/sso'
76
76
assert self .ar .session_id () == "id12"
77
77
assert self .ar .ava ["givenName" ] == IDENTITY ["givenName" ]
78
78
assert self .ar .name_id
79
79
assert self .ar .issuer () == 'urn:mace:example.com:saml:roland:idp'
80
-
80
+
81
81
def test_verify_signed_1 (self ):
82
82
xml_response = self ._sign_resp_
83
83
print (xml_response )
84
-
84
+
85
85
self .ar .outstanding_queries = {"id12" : "http://localhost:8088/sso" }
86
86
self .ar .timeslack = 10000
87
87
self .ar .loads (xml_response , decode = False )
88
88
self .ar .verify ()
89
-
89
+
90
90
print (self .ar .__dict__ )
91
91
assert self .ar .came_from == 'http://localhost:8088/sso'
92
92
assert self .ar .session_id () == "id12"
@@ -98,14 +98,14 @@ def test_parse_2(self):
98
98
with open (XML_RESPONSE_FILE ) as fp :
99
99
xml_response = fp .read ()
100
100
ID = "bahigehogffohiphlfmplepdpcohkhhmheppcdie"
101
- self .ar .outstanding_queries = {ID : "http://localhost:8088/foo" }
101
+ self .ar .outstanding_queries = {ID : "http://localhost:8088/foo" }
102
102
self .ar .return_addr = "http://xenosmilus.umdc.umu.se:8087/login"
103
103
self .ar .entity_id = "xenosmilus.umdc.umu.se"
104
104
# roughly a year, should create the response on the fly
105
105
self .ar .timeslack = 315360000 # indecent long time
106
106
self .ar .loads (xml_response , decode = False )
107
107
self .ar .verify ()
108
-
108
+
109
109
print (self .ar .__dict__ )
110
110
assert self .ar .came_from == 'http://localhost:8088/foo'
111
111
assert self .ar .session_id () == ID
@@ -189,8 +189,78 @@ def test_unpack_nested_eptid(self):
189
189
resp .loads (authn_response_xml , False )
190
190
resp .parse_assertion ()
191
191
ava = resp .get_identity ()
192
+ assert len (ava ) == 1
192
193
assert ava ["eduPersonTargetedID" ] == ["b8e734571d9adb0e6444a5b49a22f4206df24d88" ]
193
194
195
+ def test_multiple_attribute_statement (self ):
196
+ authn_response_xml = """<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
197
+ xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
198
+ ID="CORTO54673f841c5297dd3614527d38e217332f9e3000"
199
+ Version="2.0"
200
+ IssueInstant="2016-09-23T14:00:45Z"
201
+ Destination="https://sp.example.com/acs/post"
202
+ InResponseTo="id-Wnv7CMQO1pFJoRWgi"
203
+ >
204
+ <saml:Issuer>https://idp.example.com</saml:Issuer>
205
+ <samlp:Status>
206
+ <samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" />
207
+ </samlp:Status>
208
+ <saml:Assertion xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
209
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
210
+ ID="CORTOadad7cb5e1237cf30fa7ab49544c15eec582854e"
211
+ Version="2.0"
212
+ IssueInstant="2016-09-23T14:00:45Z"
213
+ >
214
+ <saml:Issuer>https://idp.example.com</saml:Issuer>
215
+ <saml:Subject>
216
+ <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">b8e734571d9adb0e6444a5b49a22f4206df24d88</saml:NameID>
217
+ <saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
218
+ <saml:SubjectConfirmationData Recipient="https://sp.example.com/acs/post"
219
+ InResponseTo="id-Wnv7CMQO1pFJoRWgi"
220
+ />
221
+ </saml:SubjectConfirmation>
222
+ </saml:Subject>
223
+ <saml:Conditions NotBefore="2016-09-23T14:00:44Z">
224
+ <saml:AudienceRestriction>
225
+ <saml:Audience>https://sp.example.com</saml:Audience>
226
+ </saml:AudienceRestriction>
227
+ </saml:Conditions>
228
+ <saml:AuthnStatement AuthnInstant="2016-09-23T13:55:40Z"
229
+ SessionIndex="_9f1148918f12525c6cad9aea29bc557afab2cb8c33"
230
+ >
231
+ <saml:AuthnContext>
232
+ <saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:Password</saml:AuthnContextClassRef>
233
+ <saml:AuthenticatingAuthority>https://idp.example.com</saml:AuthenticatingAuthority>
234
+ </saml:AuthnContext>
235
+ </saml:AuthnStatement>
236
+ <saml:AttributeStatement>
237
+ <saml:Attribute Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.10"
238
+ NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
239
+ >
240
+ <saml:AttributeValue>
241
+ <saml:NameID Format="urn:oasis:names:tc:SAML:2.0:nameid-format:persistent">b8e734571d9adb0e6444a5b49a22f4206df24d88</saml:NameID>
242
+ </saml:AttributeValue>
243
+ </saml:Attribute>
244
+ </saml:AttributeStatement>
245
+ <saml:AttributeStatement>
246
+ <saml:Attribute Name="name"
247
+ NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified"
248
+ >
249
+ <saml:AttributeValue xsi:type="xs:string">John Doe</saml:AttributeValue>
250
+ </saml:Attribute>
251
+ </saml:AttributeStatement>
252
+ </saml:Assertion>
253
+ </samlp:Response>"""
254
+
255
+ resp = authn_response (self .conf , "https://sp.example.com/acs/post" , asynchop = False , allow_unsolicited = True )
256
+ resp .loads (authn_response_xml , False )
257
+ resp .parse_assertion ()
258
+ ava = resp .get_identity ()
259
+ assert len (ava ) == 2
260
+ assert ava ["eduPersonTargetedID" ] == ["b8e734571d9adb0e6444a5b49a22f4206df24d88" ]
261
+ assert ava ["name" ] == ["John Doe" ]
262
+
263
+
194
264
if __name__ == "__main__" :
195
265
t = TestAuthnResponse ()
196
266
t .setup_class ()
0 commit comments