saml2 3.1.2 → 3.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +6 -4
  3. data/exe/bulk_verify_responses +94 -0
  4. data/lib/saml2/assertion.rb +7 -7
  5. data/lib/saml2/attribute/x500.rb +31 -28
  6. data/lib/saml2/attribute.rb +53 -49
  7. data/lib/saml2/attribute_consuming_service.rb +29 -31
  8. data/lib/saml2/authn_request.rb +54 -47
  9. data/lib/saml2/authn_statement.rb +31 -20
  10. data/lib/saml2/base.rb +72 -63
  11. data/lib/saml2/bindings/http_post.rb +7 -7
  12. data/lib/saml2/bindings/http_redirect.rb +37 -33
  13. data/lib/saml2/bindings.rb +1 -1
  14. data/lib/saml2/conditions.rb +19 -16
  15. data/lib/saml2/contact.rb +19 -18
  16. data/lib/saml2/endpoint.rb +14 -11
  17. data/lib/saml2/entity.rb +27 -27
  18. data/lib/saml2/identity_provider.rb +13 -10
  19. data/lib/saml2/indexed_object.rb +15 -12
  20. data/lib/saml2/key.rb +43 -34
  21. data/lib/saml2/localized_name.rb +11 -10
  22. data/lib/saml2/logout_request.rb +8 -8
  23. data/lib/saml2/logout_response.rb +4 -4
  24. data/lib/saml2/message.rb +24 -20
  25. data/lib/saml2/name_id.rb +45 -41
  26. data/lib/saml2/namespaces.rb +8 -8
  27. data/lib/saml2/organization.rb +11 -10
  28. data/lib/saml2/organization_and_contacts.rb +5 -5
  29. data/lib/saml2/request.rb +3 -3
  30. data/lib/saml2/requested_authn_context.rb +4 -4
  31. data/lib/saml2/response.rb +45 -33
  32. data/lib/saml2/role.rb +11 -11
  33. data/lib/saml2/schemas.rb +13 -10
  34. data/lib/saml2/service_provider.rb +11 -12
  35. data/lib/saml2/signable.rb +23 -18
  36. data/lib/saml2/sso.rb +5 -5
  37. data/lib/saml2/status.rb +9 -7
  38. data/lib/saml2/status_response.rb +5 -5
  39. data/lib/saml2/subject.rb +28 -28
  40. data/lib/saml2/version.rb +1 -1
  41. data/lib/saml2.rb +7 -7
  42. metadata +78 -122
  43. data/spec/fixtures/FederationMetadata.xml +0 -670
  44. data/spec/fixtures/authnrequest.xml +0 -12
  45. data/spec/fixtures/certificate.pem +0 -24
  46. data/spec/fixtures/entities.xml +0 -13
  47. data/spec/fixtures/external-uri-reference-response.xml +0 -48
  48. data/spec/fixtures/identity_provider.xml +0 -46
  49. data/spec/fixtures/noconditions_response.xml +0 -1
  50. data/spec/fixtures/othercertificate.pem +0 -25
  51. data/spec/fixtures/privatekey.key +0 -27
  52. data/spec/fixtures/response_assertion_signed_reffed_from_response.xml +0 -6
  53. data/spec/fixtures/response_signed.xml +0 -46
  54. data/spec/fixtures/response_tampered_certificate.xml +0 -25
  55. data/spec/fixtures/response_tampered_signature.xml +0 -46
  56. data/spec/fixtures/response_with_attribute_signed.xml +0 -46
  57. data/spec/fixtures/response_with_encrypted_assertion.xml +0 -58
  58. data/spec/fixtures/response_with_rsa_key_value.xml +0 -1
  59. data/spec/fixtures/response_with_signed_assertion_and_encrypted_subject.xml +0 -116
  60. data/spec/fixtures/response_without_keyinfo.xml +0 -1
  61. data/spec/fixtures/service_provider.xml +0 -79
  62. data/spec/fixtures/test3-response.xml +0 -9
  63. data/spec/fixtures/test6-response.xml +0 -10
  64. data/spec/fixtures/test7-response.xml +0 -10
  65. data/spec/fixtures/xml_missigned_assertion.xml +0 -84
  66. data/spec/fixtures/xml_signature_wrapping_attack_duplicate_ids.xml +0 -11
  67. data/spec/fixtures/xml_signature_wrapping_attack_response_attributes.xml +0 -45
  68. data/spec/fixtures/xml_signature_wrapping_attack_response_nameid.xml +0 -44
  69. data/spec/fixtures/xslt-transform-response.xml +0 -57
  70. data/spec/lib/attribute_consuming_service_spec.rb +0 -129
  71. data/spec/lib/attribute_spec.rb +0 -149
  72. data/spec/lib/authn_request_spec.rb +0 -52
  73. data/spec/lib/bindings/http_redirect_spec.rb +0 -183
  74. data/spec/lib/conditions_spec.rb +0 -74
  75. data/spec/lib/entity_spec.rb +0 -58
  76. data/spec/lib/identity_provider_spec.rb +0 -43
  77. data/spec/lib/indexed_object_spec.rb +0 -71
  78. data/spec/lib/key_spec.rb +0 -23
  79. data/spec/lib/logout_request_spec.rb +0 -33
  80. data/spec/lib/logout_response_spec.rb +0 -33
  81. data/spec/lib/message_spec.rb +0 -23
  82. data/spec/lib/response_spec.rb +0 -293
  83. data/spec/lib/service_provider_spec.rb +0 -76
  84. data/spec/lib/signable_spec.rb +0 -15
  85. data/spec/spec_helper.rb +0 -8
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../spec_helper'
4
-
5
- module SAML2
6
- describe LogoutRequest do
7
- let(:idp) { Entity.parse(fixture('identity_provider.xml')).roles.first }
8
-
9
- let(:logout_request) {
10
- LogoutRequest.initiate(idp,
11
- NameID.new('issuer'),
12
- NameID.new('jacob',
13
- name_qualifier: "a",
14
- sp_name_qualifier: "b"),
15
- "abc")
16
- }
17
-
18
- it "should generate valid XML" do
19
- xml = logout_request.to_s
20
- expect(Schemas.protocol.validate(Nokogiri::XML(xml))).to eq []
21
- end
22
-
23
- it "parses" do
24
- # yup, I'm lazy
25
- new_request = LogoutRequest.parse(logout_request.to_s)
26
- expect(new_request.issuer.id).to eq 'issuer'
27
- expect(new_request.name_id.id).to eq 'jacob'
28
- expect(new_request.name_id.name_qualifier).to eq 'a'
29
- expect(new_request.name_id.sp_name_qualifier).to eq 'b'
30
- expect(new_request.session_index).to eq ['abc']
31
- end
32
- end
33
- end
@@ -1,33 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../spec_helper'
4
-
5
- module SAML2
6
- describe LogoutResponse do
7
- let(:idp) { Entity.parse(fixture('identity_provider.xml')).roles.first }
8
-
9
- let(:logout_request) {
10
- LogoutRequest.initiate(idp,
11
- NameID.new('issuer'),
12
- NameID.new('jacob',
13
- name_qualifier: "a",
14
- sp_name_qualifier: "b"),
15
- "abc")
16
- }
17
- let(:logout_response) {
18
- LogoutResponse.respond_to(logout_request, idp, NameID.new('issuer2'))
19
- }
20
-
21
- it "should generate valid XML" do
22
- xml = logout_response.to_s
23
- expect(Schemas.protocol.validate(Nokogiri::XML(xml))).to eq []
24
- end
25
-
26
- it "parses" do
27
- # yup, I'm lazy
28
- new_response = LogoutResponse.parse(logout_response.to_s)
29
- expect(new_response.issuer.id).to eq 'issuer2'
30
- expect(new_response.status.code).to eq Status::SUCCESS
31
- end
32
- end
33
- end
@@ -1,23 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../spec_helper'
4
-
5
- module SAML2
6
- describe Message do
7
- describe '.parse' do
8
- it 'complains about invalid XML' do
9
- expect { Message.parse("garbage") }.to raise_error(CorruptMessage)
10
- end
11
-
12
- it 'complains about getting the wrong type if calling on a subclass, and you get a different type' do
13
- expect { Response.parse(fixture('authnrequest.xml')) }.to raise_error(UnexpectedMessage)
14
- end
15
- end
16
-
17
- describe '.from_xml' do
18
- it "complains about unknown messages" do
19
- expect { Message.parse("<Garbage></Garbage>") }.to raise_error(UnknownMessage)
20
- end
21
- end
22
- end
23
- end
@@ -1,293 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../spec_helper'
4
-
5
- module SAML2
6
- describe Response do
7
- let(:sp_entity) { Entity.parse(fixture('service_provider.xml')) }
8
- let(:sp) { sp_entity.roles.first }
9
-
10
- let(:request) do
11
- request = AuthnRequest.parse(fixture('authnrequest.xml'))
12
- request.resolve(sp)
13
- request
14
- end
15
-
16
- let(:response) do
17
- Response.respond_to(request,
18
- NameID.new('issuer'),
19
- NameID.new('jacob', NameID::Format::PERSISTENT))
20
- end
21
-
22
- it "should generate valid XML" do
23
- xml = response.to_s
24
- expect(Schemas.protocol.validate(Nokogiri::XML(xml))).to eq []
25
- end
26
-
27
- def freeze_response
28
- response.instance_variable_set(:@id, "_9a15e699-2d04-4ba7-a521-cfa4dcd21f44")
29
- assertion = response.assertions.first
30
- assertion.instance_variable_set(:@id, "_cdfc3faf-90ad-462f-880d-677483210684")
31
- response.instance_variable_set(:@issue_instant, Time.parse("2015-02-12T22:51:29Z"))
32
- assertion.instance_variable_set(:@issue_instant, Time.parse("2015-02-12T22:51:29Z"))
33
- assertion.conditions.not_before = Time.parse("2015-02-12T22:51:24Z")
34
- assertion.conditions.not_on_or_after = Time.parse("2015-02-12T22:51:59Z")
35
- assertion.statements.first.authn_instant = Time.parse("2015-02-12T22:51:29Z")
36
- confirmation = assertion.subject.confirmation
37
- confirmation.not_on_or_after = Time.parse("2015-02-12T22:54:29Z")
38
- confirmation.recipient = response.destination
39
- confirmation.in_response_to = response.in_response_to
40
- end
41
-
42
- it "should generate a valid signature" do
43
- freeze_response
44
- response.sign(fixture('certificate.pem'), fixture('privatekey.key'))
45
- expect(Schemas.protocol.validate(response.to_xml)).to eq []
46
- # verifiable on the command line with:
47
- # xmlsec1 --verify --pubkey-cert-pem certificate.pem --privkey-pem privatekey.key --id-attr:ID urn:oasis:names:tc:SAML:2.0:assertion:Assertion response_signed.xml
48
- expect(response.to_s).to eq fixture('response_signed.xml')
49
- end
50
-
51
- it "should generate a valid signature when attributes are present" do
52
- freeze_response
53
- response.assertions.first.statements << sp.attribute_consuming_services.default.create_statement('givenName' => 'cody')
54
- response.sign(fixture('certificate.pem'), fixture('privatekey.key'))
55
- expect(response.to_s).to eq fixture('response_with_attribute_signed.xml')
56
- end
57
-
58
- it "should generate valid XML for IdP initiated response" do
59
- response = Response.initiate(sp, NameID.new('issuer'),
60
- NameID.new('jacob', NameID::Format::PERSISTENT))
61
- expect(Schemas.protocol.validate(Nokogiri::XML(response.to_s))).to eq []
62
- end
63
-
64
- it "parses a serialized assertion" do
65
- response2 = Message.parse(response.to_s)
66
- expect(response2.in_response_to).not_to be_nil
67
- expect(response2.in_response_to).to eq response.in_response_to
68
- expect(response2.assertions.length).to eq 1
69
- expect(response2.assertions.first.subject.name_id.id).to eq 'jacob'
70
- end
71
-
72
- it "doesn't validate a response with XSLT transforms" do
73
- response = Response.parse(fixture("xslt-transform-response.xml"))
74
- expect(response).to be_valid_schema
75
- expect(response.assertions.first.valid_signature?(fingerprint: 'bc71f7bacb36011694405dd0e2beafcc069de45f')).to eq false
76
- end
77
-
78
- it "doesn't validate a response with external URI reference in the signature" do
79
- response = Response.parse(fixture("external-uri-reference-response.xml"))
80
- expect(response).to be_valid_schema
81
- expect(response.assertions.first.valid_signature?(fingerprint: 'bc71f7bacb36011694405dd0e2beafcc069de45f')).to eq false
82
- end
83
-
84
- it "can decrypt an EncryptedAssertion" do
85
- # verifiable on the command line with:
86
- # xmlsec1 decrypt --privkey-pem privatekey.key response_with_encrypted_assertion.xml
87
- response = Response.parse(fixture("response_with_encrypted_assertion.xml"))
88
- expect(response.decrypt(fixture("privatekey.key"))).to eq true
89
- expect(response.assertions.length).to eq 1
90
- expect(response.assertions.first.subject.name_id.id).to eq 'jacob'
91
- end
92
-
93
- it "allows non-ascii characters in attributes" do
94
- response = Response.parse(fixture("test6-response.xml"))
95
-
96
- attributes = response.assertions.first.attribute_statements.first.to_h
97
- expect(attributes['eduPersonAffiliation']).to eq 'member'
98
- expect(attributes['givenName']).to eq 'Canvas'
99
- expect(attributes['displayName']).to eq 'Canvas Üser'
100
- end
101
-
102
- # see CVE-2017-11428
103
- it "returns the full content of the NameID, even if a comment-insertion attack allows it to still validate the signature" do
104
- response = Response.parse(fixture("test7-response.xml"))
105
- # this file is a copy of test6-response.xml, with a comment inserted into the NameID
106
-
107
- # the signature is still valid (we have to set a weird verification time because the response
108
- # was signed with an expired signature)
109
- expect(response.validate_signature(fingerprint: 'afe71c28ef740bc87425be13a2263d37971da1f9')).to eq []
110
-
111
- # the comment is ignored, but doesn't truncate the nameid
112
- expect(response.assertions.first.subject.name_id.id).to eq 'testuser@example.com'
113
- end
114
-
115
- it "doesn't choke on missing Conditions" do
116
- response = Response.parse(fixture("noconditions_response.xml"))
117
- expect(response.assertions.first.conditions).to eq nil
118
- end
119
-
120
- describe "#validate" do
121
- let (:idp_entity) do
122
- idp_entity = Entity.new("issuer")
123
- idp = IdentityProvider.new
124
- idp.keys << KeyDescriptor.new(fixture("certificate.pem"))
125
- idp_entity.roles << idp
126
-
127
- idp_entity
128
- end
129
-
130
- before do
131
- sp.private_keys << OpenSSL::PKey::RSA.new(fixture("privatekey.key"))
132
- end
133
-
134
- it "succeeds" do
135
- response = Response.parse(fixture("response_signed.xml"))
136
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2015-02-12T22:51:30Z'))
137
- expect(response.errors).to eq []
138
- end
139
-
140
- it "checks the issuer" do
141
- response = Response.parse(fixture("response_signed.xml"))
142
- idp_entity.entity_id = 'someoneelse'
143
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2015-02-12T22:51:30Z'))
144
- expect(response.errors).to eq ["received unexpected message from 'issuer'; expected it to be from 'someoneelse'"]
145
- end
146
-
147
- it "complains about old message" do
148
- response = Response.parse(fixture("response_signed.xml"))
149
- sp_entity.valid_response?(response, idp_entity)
150
- expect(response.errors.length).to eq 1
151
- expect(response.errors.first).to match (/not_on_or_after .* is earlier than/)
152
- end
153
-
154
- it "complains about mismatched audience restriction" do
155
- response = Response.parse(fixture("response_signed.xml"))
156
- sp_entity.entity_id = 'someoneelse'
157
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2015-02-12T22:51:30Z'))
158
- expect(response.errors).to eq ["audience someoneelse not in allowed list of http://siteadmin.instructure.com/saml2"]
159
- end
160
-
161
- it "complains about no signature" do
162
- response = Response.parse(fixture("response_with_encrypted_assertion.xml"))
163
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2015-02-12T22:51:30Z'))
164
- expect(response.errors).to eq ["neither response nor assertion were signed"]
165
- end
166
-
167
- it "complains if the signature has been tampered with" do
168
- response = Response.parse(fixture("response_tampered_signature.xml"))
169
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2015-02-12T22:51:30Z'))
170
- expect(response.errors).to eq ["signature is invalid"]
171
- end
172
-
173
- it "complains if the trusted certificate isn't what signed the response" do
174
- idp_entity.identity_providers.first.keys.clear
175
- idp_entity.identity_providers.first.fingerprints << "afe71c28ef740bc87425be13a2263d37971da1f9"
176
-
177
- response = Response.parse(fixture("response_tampered_certificate.xml"))
178
- sp_entity.valid_response?(response, idp_entity,
179
- verification_time: Time.parse('2015-02-12T22:51:30Z'))
180
- expect(response.errors).to eq ["signature is invalid"]
181
- end
182
-
183
- it "complains when we don't have any trusted keys" do
184
- response = Response.parse(fixture("response_signed.xml"))
185
- idp_entity.identity_providers.first.keys.clear
186
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2015-02-12T22:51:30Z'))
187
- expect(response.errors).to eq ["could not find certificate to validate message"]
188
- end
189
-
190
- it "complains about a valid signature we don't trust" do
191
- response = Response.parse(fixture("response_signed.xml"))
192
- idp_entity.identity_providers.first.keys.clear
193
- idp_entity.identity_providers.first.keys << KeyDescriptor.new(fixture("othercertificate.pem"))
194
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2015-02-12T22:51:30Z'))
195
- expect(response.errors.length).to eq 1
196
- expect(response.errors.first).to eq("no trusted signing key found")
197
- end
198
-
199
- it "validates signature by fingerprint" do
200
- response = Response.parse(fixture("response_signed.xml"))
201
- idp_entity.identity_providers.first.keys.clear
202
- idp_entity.identity_providers.first.fingerprints << "1c:37:7d:30:c1:83:18:ea:20:8b:dc:d5:35:b6:16:85:17:58:f7:c9"
203
-
204
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2015-02-12T22:51:30Z'))
205
- expect(response.errors).to eq []
206
- end
207
-
208
- it "complains when we don't have any trusted fingerprints" do
209
- response = Response.parse(fixture("response_signed.xml"))
210
- idp_entity.identity_providers.first.keys.clear
211
- idp_entity.identity_providers.first.fingerprints << "1c:37:7d:30:c1:83:18:ea:20:8b:dc:d5:35:b6:16:85:17:58:f7:ca"
212
-
213
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2015-02-12T22:51:30Z'))
214
- expect(response.errors).to eq ["no trusted signing key found"]
215
- end
216
-
217
- it "protects against xml signature wrapping attacks targeting nameid" do
218
- response = Response.parse(fixture("xml_signature_wrapping_attack_response_nameid.xml"))
219
- idp_entity.identity_providers.first.keys.clear
220
- idp_entity.identity_providers.first.fingerprints << "afe71c28ef740bc87425be13a2263d37971da1f9"
221
-
222
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2012-08-03T20:07:16Z'))
223
- expect(response.errors.length).to eq 1
224
- expect(response.errors.first.to_s).to eq "5:0: ERROR: Element '{urn:oasis:names:tc:SAML:2.0:assertion}Assertion': This element is not expected. Expected is one of ( {http://www.w3.org/2000/09/xmldsig#}Signature, {urn:oasis:names:tc:SAML:2.0:protocol}Extensions, {urn:oasis:names:tc:SAML:2.0:protocol}Status )."
225
- end
226
-
227
- it "protects against xml signature wrapping attacks targeting attributes" do
228
- response = Response.parse(fixture("xml_signature_wrapping_attack_response_attributes.xml"))
229
- idp_entity.identity_providers.first.keys.clear
230
- idp_entity.identity_providers.first.fingerprints << "afe71c28ef740bc87425be13a2263d37971da1f9"
231
-
232
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2012-08-03T20:07:16Z'))
233
- expect(response.errors.length).to eq 1
234
- expect(response.errors.first.to_s).to eq "30:0: ERROR: Element '{urn:oasis:names:tc:SAML:2.0:assertion}Subject': This element is not expected."
235
- end
236
-
237
- it "protects against xml signature wrapping attacks with duplicate IDs" do
238
- response = Response.parse(fixture("xml_signature_wrapping_attack_duplicate_ids.xml"))
239
- idp_entity.identity_providers.first.keys.clear
240
- idp_entity.identity_providers.first.fingerprints << "7292914fc5bffa6f3fe1e43fd47c205395fecfa2"
241
-
242
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2014-02-01T13:48:10.831Z'))
243
- expect(response.errors.length).to eq 1
244
- expect(response.errors.first.to_s).to eq "1:0: ERROR: Element '{urn:oasis:names:tc:SAML:2.0:assertion}Assertion', attribute 'ID': 'pfx77d6c794-8295-f1c4-298e-c25ecae8046d' is not a valid value of the atomic type 'xs:ID'."
245
- end
246
-
247
- it "protects against additional mis-signed assertions" do
248
- response = Response.parse(fixture("xml_missigned_assertion.xml"))
249
- idp_entity.identity_providers.first.keys.clear
250
- idp_entity.identity_providers.first.fingerprints << "c38e789fcfbbd4727bd8ff7fc365b44fc3596bda"
251
-
252
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2015-02-27T19:12:52Z'))
253
- expect(response.errors.map(&:to_s)).to eq ["2:0: ERROR: Element '{http://www.w3.org/2000/09/xmldsig#}Signature': This element is not expected.",
254
- "43:0: ERROR: Element '{http://www.w3.org/2000/09/xmldsig#}Signature': This element is not expected."]
255
- end
256
-
257
- it "doesn't break the signature by decrypting elements first" do
258
- response = Response.parse(fixture("response_with_signed_assertion_and_encrypted_subject.xml"))
259
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2015-02-12T22:51:30Z'))
260
- expect(response.errors).to eq []
261
- expect(response.assertions.first.subject.name_id.id).to eq 'jacob'
262
- end
263
-
264
- it "allows signatures that don't include KeyInfo, if we have a full cert" do
265
- response = Response.parse(fixture("response_without_keyinfo.xml"))
266
- sp_entity.entity_id = 'http://unimelb-dev.instructure.com/saml2'
267
- idp_entity.entity_id = 'https://authidm3tst.unimelb.edu.au:443/oam/fed'
268
- idp_entity.identity_providers.first.keys.clear
269
- idp_entity.identity_providers.first.keys << KeyDescriptor.new(<<-CERTIFICATE)
270
- MIIB/jCCAWegAwIBAgIBCjANBgkqhkiG9w0BAQQFADAkMSIwIAYDVQQDExlhZGRlcjEuaXRzLnVuaW1lbGIuZWR1LmF1MB4XDTE3MDUyMjA2MzQzOFoXDTI3MDUyMDA2MzQzOFowJDEiMCAGA1UEAxMZYWRkZXIxLml0cy51bmltZWxiLmVkdS5hdTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAjJgoa5bPS+Jukq2vNaMwZ39L3IhAg6oOytz+bgOhmF+o5zYARbFqC67faa/rMSkfQwYIpp/MdsC8XHtHeR6HCJjbuPkH/EooHiREOClTI0EKZvI2Xv/DqexxEegRPxXiwPUEPozGGT1yWtSwkQTvRvA9tMpZl3yLg1LhDOP6s6MCAwEAAaNAMD4wDAYDVR0TAQH/BAIwADAPBgNVHQ8BAf8EBQMDB9gAMB0GA1UdDgQWBBRukBh7J1okLMIfSRpzF5opuj0LizANBgkqhkiG9w0BAQQFAAOBgQB0zySVaypIGRksTwpmjaQhMvNrYWGvj74Rs1iuqOdsEQkpgk5dQKRFiAFEr+6b7WN4k+IAH5S++l1R0bUG6k9HFSn7uy7AD+qZcdoUm9a39brtH2kefs0D3bQfrwkqggAtWKwqfU4r7nAcdtVE+CT3cny5QU2/mJav9W9bzFPMXQ==
271
- CERTIFICATE
272
-
273
- sp_entity.valid_response?(response, idp_entity, verification_time: Time.parse('2019-04-16T00:56:03Z'))
274
- expect(response.errors).to eq []
275
- expect(response.assertions.first.subject.name_id.id).to eq 'testuserint.sso@staff.oimtest.unimelb.edu.au'
276
- end
277
-
278
- it "finds signatures the sign the assertion, not inside the assertion" do
279
- response = Response.parse(fixture("response_assertion_signed_reffed_from_response.xml"))
280
- sp_entity.entity_id = 'http://wscc.instructure.com/saml2'
281
- idp_entity.entity_id = 'https://my.wscc.edu/idp'
282
- idp_entity.identity_providers.first.keys.clear
283
- idp_entity.identity_providers.first.fingerprints << "c4f473274116a3cbc295c3abf77c7ed1ade9b904"
284
-
285
- sp_entity.valid_response?(response, idp_entity, verification_time: response.issue_instant)
286
- expect(response.errors).to eq []
287
- expect(response.assertions.first.subject.name_id.id).to eq 'narnold@wscc.edu'
288
- expect(response).not_to be_signed
289
- expect(response.assertions.first).to be_signed
290
- end
291
- end
292
- end
293
- end
@@ -1,76 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../spec_helper'
4
-
5
- module SAML2
6
- describe ServiceProvider do
7
- it "should serialize valid xml" do
8
- entity = Entity.new
9
- entity.entity_id = 'http://sso.canvaslms.com/SAML2'
10
- entity.organization = Organization.new('Canvas', 'Canvas by Instructure', 'https://www.canvaslms.com/')
11
- contact = Contact.new(Contact::Type::TECHNICAL)
12
- contact.company = 'Instructure'
13
- contact.email_addresses << 'mailto:ops@instructure.com'
14
- entity.contacts << contact
15
-
16
- sp = ServiceProvider.new
17
- sp.single_logout_services << Endpoint.new('https://sso.canvaslms.com/SAML2/Logout',
18
- Bindings::HTTPRedirect::URN)
19
- sp.assertion_consumer_services << Endpoint::Indexed.new('https://sso.canvaslms.com/SAML2/Login1')
20
- sp.assertion_consumer_services << Endpoint::Indexed.new('https://sso.canvaslms.com/SAML2/Login2')
21
- sp.keys << KeyDescriptor.new('somedata', KeyDescriptor::Type::ENCRYPTION, [KeyDescriptor::EncryptionMethod.new])
22
- sp.keys << KeyDescriptor.new('somedata', KeyDescriptor::Type::SIGNING)
23
- acs = AttributeConsumingService.new
24
- acs.name[:en] = 'service'
25
- acs.requested_attributes << RequestedAttribute.create('uid')
26
- sp.attribute_consuming_services << acs
27
-
28
- entity.roles << sp
29
- expect(Schemas.metadata.validate(Nokogiri::XML(entity.to_s))).to eq []
30
- end
31
-
32
- describe "valid metadata" do
33
- let(:entity) { Entity.parse(fixture('service_provider.xml')) }
34
- let(:sp) { entity.roles.first }
35
-
36
- it "should create the assertion_consumer_services array" do
37
- expect(sp.assertion_consumer_services.length).to eq 4
38
- expect(sp.assertion_consumer_services.map(&:index)).to eq [0, 1, 2, 3]
39
- expect(sp.assertion_consumer_services.first.location).to eq 'https://siteadmin.instructure.com/saml_consume'
40
- end
41
-
42
- it "should find the signing certificate" do
43
- expect(sp.signing_keys.first.x509).to match(/MIIE8TCCA9mgAwIBAgIJAITusxON60cKMA0GCSqGSIb3DQEBBQUAMIGrMQswCQYD/)
44
- end
45
-
46
- it "should load the organization" do
47
- expect(entity.organization.display_name.to_s).to eq 'Canvas'
48
- end
49
-
50
- it "should load contacts" do
51
- expect(entity.contacts.length).to eq 1
52
- expect(entity.contacts.first.type).to eq Contact::Type::TECHNICAL
53
- expect(entity.contacts.first.surname).to eq 'Administrator'
54
- end
55
-
56
- it "loads attribute_consuming_services" do
57
- expect(sp.attribute_consuming_services.length).to eq 1
58
- acs = sp.attribute_consuming_services.first
59
- expect(acs.index).to eq 0
60
- expect(acs.name.to_s).to eq 'service'
61
- expect(acs.requested_attributes.length).to eq 1
62
- expect(acs.requested_attributes.first.name).to eq 'urn:oid:2.5.4.42'
63
- end
64
-
65
- it "loads the key info" do
66
- expect(sp.keys.first.encryption_methods.first.algorithm).to eq KeyDescriptor::EncryptionMethod::Algorithm::AES128_CBC
67
- expect(sp.keys.first.encryption_methods.first.key_size).to eq 128
68
- end
69
-
70
- it "loads service provider attributes" do
71
- expect(sp.authn_requests_signed?).to be_truthy
72
- expect(sp.want_assertions_signed?).to be_truthy
73
- end
74
- end
75
- end
76
- end
@@ -1,15 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require_relative '../spec_helper'
4
-
5
- module SAML2
6
- describe Signable do
7
- describe '#valid_signature?' do
8
- it 'can work with an explicit key from metadata' do
9
- response = Response.parse(fixture("response_with_rsa_key_value.xml"))
10
- key = response.assertions.first.signing_key.key
11
- expect(response.assertions.first.valid_signature?(key: [key])).to eq true
12
- end
13
- end
14
- end
15
- end
data/spec/spec_helper.rb DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'byebug'
4
- require 'saml2'
5
-
6
- def fixture(name)
7
- File.read(File.expand_path(File.join(__FILE__, "../fixtures", name)))
8
- end