saml2 3.1.2 → 3.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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