ruby-saml 1.10.1 → 1.12.2

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.

Potentially problematic release.


This version of ruby-saml might be problematic. Click here for more details.

Files changed (159) hide show
  1. checksums.yaml +7 -7
  2. data/.travis.yml +21 -20
  3. data/README.md +95 -26
  4. data/changelog.md +40 -0
  5. data/lib/onelogin/ruby-saml/attributes.rb +24 -1
  6. data/lib/onelogin/ruby-saml/authrequest.rb +11 -6
  7. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +70 -24
  8. data/lib/onelogin/ruby-saml/logging.rb +3 -3
  9. data/lib/onelogin/ruby-saml/logoutrequest.rb +11 -5
  10. data/lib/onelogin/ruby-saml/logoutresponse.rb +21 -2
  11. data/lib/onelogin/ruby-saml/metadata.rb +11 -3
  12. data/lib/onelogin/ruby-saml/response.rb +64 -23
  13. data/lib/onelogin/ruby-saml/saml_message.rb +6 -0
  14. data/lib/onelogin/ruby-saml/setting_error.rb +6 -0
  15. data/lib/onelogin/ruby-saml/settings.rb +72 -7
  16. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +20 -1
  17. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +31 -17
  18. data/lib/onelogin/ruby-saml/utils.rb +69 -0
  19. data/lib/onelogin/ruby-saml/version.rb +1 -1
  20. data/lib/xml_security.rb +34 -6
  21. data/ruby-saml.gemspec +9 -5
  22. metadata +161 -383
  23. data/test/certificates/certificate.der +0 -0
  24. data/test/certificates/certificate1 +0 -12
  25. data/test/certificates/certificate_without_head_foot +0 -1
  26. data/test/certificates/formatted_certificate +0 -14
  27. data/test/certificates/formatted_chained_certificate +0 -42
  28. data/test/certificates/formatted_private_key +0 -12
  29. data/test/certificates/formatted_rsa_private_key +0 -12
  30. data/test/certificates/invalid_certificate1 +0 -1
  31. data/test/certificates/invalid_certificate2 +0 -1
  32. data/test/certificates/invalid_certificate3 +0 -12
  33. data/test/certificates/invalid_chained_certificate1 +0 -1
  34. data/test/certificates/invalid_private_key1 +0 -1
  35. data/test/certificates/invalid_private_key2 +0 -1
  36. data/test/certificates/invalid_private_key3 +0 -10
  37. data/test/certificates/invalid_rsa_private_key1 +0 -1
  38. data/test/certificates/invalid_rsa_private_key2 +0 -1
  39. data/test/certificates/invalid_rsa_private_key3 +0 -10
  40. data/test/certificates/ruby-saml-2.crt +0 -15
  41. data/test/certificates/ruby-saml.crt +0 -14
  42. data/test/certificates/ruby-saml.key +0 -15
  43. data/test/idp_metadata_parser_test.rb +0 -587
  44. data/test/logging_test.rb +0 -62
  45. data/test/logout_requests/invalid_slo_request.xml +0 -6
  46. data/test/logout_requests/slo_request.xml +0 -4
  47. data/test/logout_requests/slo_request.xml.base64 +0 -1
  48. data/test/logout_requests/slo_request_deflated.xml.base64 +0 -1
  49. data/test/logout_requests/slo_request_with_name_id_format.xml +0 -4
  50. data/test/logout_requests/slo_request_with_session_index.xml +0 -5
  51. data/test/logout_responses/logoutresponse_fixtures.rb +0 -86
  52. data/test/logoutrequest_test.rb +0 -260
  53. data/test/logoutresponse_test.rb +0 -409
  54. data/test/metadata/idp_descriptor.xml +0 -26
  55. data/test/metadata/idp_descriptor_2.xml +0 -56
  56. data/test/metadata/idp_descriptor_3.xml +0 -14
  57. data/test/metadata/idp_descriptor_4.xml +0 -72
  58. data/test/metadata/idp_metadata_different_sign_and_encrypt_cert.xml +0 -72
  59. data/test/metadata/idp_metadata_multi_certs.xml +0 -75
  60. data/test/metadata/idp_metadata_multi_signing_certs.xml +0 -52
  61. data/test/metadata/idp_metadata_same_sign_and_encrypt_cert.xml +0 -71
  62. data/test/metadata/idp_multiple_descriptors.xml +0 -59
  63. data/test/metadata/idp_multiple_descriptors_2.xml +0 -59
  64. data/test/metadata/no_idp_descriptor.xml +0 -21
  65. data/test/metadata_test.rb +0 -331
  66. data/test/request_test.rb +0 -340
  67. data/test/response_test.rb +0 -1620
  68. data/test/responses/adfs_response_sha1.xml +0 -46
  69. data/test/responses/adfs_response_sha256.xml +0 -46
  70. data/test/responses/adfs_response_sha384.xml +0 -46
  71. data/test/responses/adfs_response_sha512.xml +0 -46
  72. data/test/responses/adfs_response_xmlns.xml +0 -45
  73. data/test/responses/attackxee.xml +0 -13
  74. data/test/responses/invalids/duplicated_attributes.xml.base64 +0 -1
  75. data/test/responses/invalids/empty_destination.xml.base64 +0 -1
  76. data/test/responses/invalids/empty_nameid.xml.base64 +0 -1
  77. data/test/responses/invalids/encrypted_new_attack.xml.base64 +0 -1
  78. data/test/responses/invalids/invalid_audience.xml.base64 +0 -1
  79. data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
  80. data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
  81. data/test/responses/invalids/invalid_signature_position.xml.base64 +0 -1
  82. data/test/responses/invalids/invalid_subjectconfirmation_inresponse.xml.base64 +0 -1
  83. data/test/responses/invalids/invalid_subjectconfirmation_nb.xml.base64 +0 -1
  84. data/test/responses/invalids/invalid_subjectconfirmation_noa.xml.base64 +0 -1
  85. data/test/responses/invalids/invalid_subjectconfirmation_recipient.xml.base64 +0 -1
  86. data/test/responses/invalids/multiple_assertions.xml.base64 +0 -2
  87. data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
  88. data/test/responses/invalids/no_authnstatement.xml.base64 +0 -1
  89. data/test/responses/invalids/no_conditions.xml.base64 +0 -1
  90. data/test/responses/invalids/no_id.xml.base64 +0 -1
  91. data/test/responses/invalids/no_issuer_assertion.xml.base64 +0 -1
  92. data/test/responses/invalids/no_issuer_response.xml.base64 +0 -1
  93. data/test/responses/invalids/no_nameid.xml.base64 +0 -1
  94. data/test/responses/invalids/no_saml2.xml.base64 +0 -1
  95. data/test/responses/invalids/no_signature.xml.base64 +0 -1
  96. data/test/responses/invalids/no_status.xml.base64 +0 -1
  97. data/test/responses/invalids/no_status_code.xml.base64 +0 -1
  98. data/test/responses/invalids/no_subjectconfirmation_data.xml.base64 +0 -1
  99. data/test/responses/invalids/no_subjectconfirmation_method.xml.base64 +0 -1
  100. data/test/responses/invalids/response_invalid_signed_element.xml.base64 +0 -1
  101. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
  102. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
  103. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
  104. data/test/responses/invalids/status_code_responder.xml.base64 +0 -1
  105. data/test/responses/invalids/status_code_responer_and_msg.xml.base64 +0 -1
  106. data/test/responses/invalids/wrong_spnamequalifier.xml.base64 +0 -1
  107. data/test/responses/no_signature_ns.xml +0 -48
  108. data/test/responses/open_saml_response.xml +0 -56
  109. data/test/responses/response_assertion_wrapped.xml.base64 +0 -93
  110. data/test/responses/response_audience_self_closed_tag.xml.base64 +0 -1
  111. data/test/responses/response_double_status_code.xml.base64 +0 -1
  112. data/test/responses/response_encrypted_attrs.xml.base64 +0 -1
  113. data/test/responses/response_encrypted_nameid.xml.base64 +0 -1
  114. data/test/responses/response_eval.xml +0 -7
  115. data/test/responses/response_no_cert_and_encrypted_attrs.xml +0 -29
  116. data/test/responses/response_node_text_attack.xml.base64 +0 -1
  117. data/test/responses/response_node_text_attack2.xml.base64 +0 -1
  118. data/test/responses/response_node_text_attack3.xml.base64 +0 -1
  119. data/test/responses/response_unsigned_xml_base64 +0 -1
  120. data/test/responses/response_with_ampersands.xml +0 -139
  121. data/test/responses/response_with_ampersands.xml.base64 +0 -93
  122. data/test/responses/response_with_ds_namespace_at_the_root.xml.base64 +0 -1
  123. data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
  124. data/test/responses/response_with_multiple_attribute_values.xml +0 -67
  125. data/test/responses/response_with_retrieval_method.xml +0 -26
  126. data/test/responses/response_with_saml2_namespace.xml.base64 +0 -102
  127. data/test/responses/response_with_signed_assertion.xml.base64 +0 -66
  128. data/test/responses/response_with_signed_assertion_2.xml.base64 +0 -1
  129. data/test/responses/response_with_signed_assertion_3.xml +0 -30
  130. data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
  131. data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
  132. data/test/responses/response_without_attributes.xml.base64 +0 -79
  133. data/test/responses/response_without_reference_uri.xml.base64 +0 -1
  134. data/test/responses/response_wrapped.xml.base64 +0 -150
  135. data/test/responses/signed_message_encrypted_signed_assertion.xml.base64 +0 -1
  136. data/test/responses/signed_message_encrypted_unsigned_assertion.xml.base64 +0 -1
  137. data/test/responses/signed_nameid_in_atts.xml +0 -47
  138. data/test/responses/signed_unqual_nameid_in_atts.xml +0 -47
  139. data/test/responses/simple_saml_php.xml +0 -71
  140. data/test/responses/starfield_response.xml.base64 +0 -1
  141. data/test/responses/test_sign.xml +0 -43
  142. data/test/responses/unsigned_encrypted_adfs.xml +0 -23
  143. data/test/responses/unsigned_message_aes128_encrypted_signed_assertion.xml.base64 +0 -1
  144. data/test/responses/unsigned_message_aes192_encrypted_signed_assertion.xml.base64 +0 -1
  145. data/test/responses/unsigned_message_aes256_encrypted_signed_assertion.xml.base64 +0 -1
  146. data/test/responses/unsigned_message_des192_encrypted_signed_assertion.xml.base64 +0 -1
  147. data/test/responses/unsigned_message_encrypted_assertion_without_saml_namespace.xml.base64 +0 -1
  148. data/test/responses/unsigned_message_encrypted_signed_assertion.xml.base64 +0 -1
  149. data/test/responses/unsigned_message_encrypted_unsigned_assertion.xml.base64 +0 -1
  150. data/test/responses/valid_response.xml.base64 +0 -1
  151. data/test/responses/valid_response_with_formatted_x509certificate.xml.base64 +0 -1
  152. data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
  153. data/test/saml_message_test.rb +0 -56
  154. data/test/settings_test.rb +0 -329
  155. data/test/slo_logoutrequest_test.rb +0 -448
  156. data/test/slo_logoutresponse_test.rb +0 -233
  157. data/test/test_helper.rb +0 -331
  158. data/test/utils_test.rb +0 -259
  159. data/test/xml_security_test.rb +0 -421
@@ -1,329 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
-
3
- require 'onelogin/ruby-saml/settings'
4
-
5
- class SettingsTest < Minitest::Test
6
-
7
- describe "Settings" do
8
- before do
9
- @settings = OneLogin::RubySaml::Settings.new
10
- end
11
-
12
- it "should provide getters and settings" do
13
- accessors = [
14
- :idp_entity_id, :idp_sso_target_url, :idp_slo_target_url,
15
- :idp_cert, :idp_cert_fingerprint, :idp_cert_fingerprint_algorithm, :idp_cert_multi,
16
- :idp_attribute_names, :issuer, :assertion_consumer_service_url, :assertion_consumer_service_binding,
17
- :single_logout_service_url, :single_logout_service_binding,
18
- :sp_name_qualifier, :name_identifier_format, :name_identifier_value, :name_identifier_value_requested,
19
- :sessionindex, :attributes_index, :passive, :force_authn,
20
- :compress_request, :double_quote_xml_attribute_values, :protocol_binding,
21
- :security, :certificate, :private_key,
22
- :authn_context, :authn_context_comparison, :authn_context_decl_ref,
23
- :assertion_consumer_logout_service_url,
24
- :assertion_consumer_logout_service_binding
25
- ]
26
-
27
- accessors.each do |accessor|
28
- value = Kernel.rand
29
- @settings.send("#{accessor}=".to_sym, value)
30
- assert_equal value, @settings.send(accessor)
31
- end
32
-
33
- end
34
-
35
- it "create settings from hash" do
36
- config = {
37
- :assertion_consumer_service_url => "http://app.muda.no/sso",
38
- :issuer => "http://muda.no",
39
- :sp_name_qualifier => "http://sso.muda.no",
40
- :idp_sso_target_url => "http://sso.muda.no/sso",
41
- :idp_slo_target_url => "http://sso.muda.no/slo",
42
- :idp_cert_fingerprint => "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
43
- :name_identifier_format => "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
44
- :attributes_index => 30,
45
- :passive => true,
46
- :protocol_binding => 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
47
- }
48
- @settings = OneLogin::RubySaml::Settings.new(config)
49
-
50
- config.each do |k,v|
51
- assert_equal v, @settings.send(k)
52
- end
53
- end
54
-
55
- it "configure attribute service attributes correctly" do
56
- @settings.attribute_consuming_service.configure do
57
- service_name "Test Service"
58
- add_attribute :name => "Name", :name_format => "Name Format", :friendly_name => "Friendly Name"
59
- end
60
-
61
- assert_equal @settings.attribute_consuming_service.configured?, true
62
- assert_equal @settings.attribute_consuming_service.name, "Test Service"
63
- assert_equal @settings.attribute_consuming_service.attributes, [{:name => "Name", :name_format => "Name Format", :friendly_name => "Friendly Name" }]
64
- end
65
-
66
- it "does not modify default security settings" do
67
- settings = OneLogin::RubySaml::Settings.new
68
- settings.security[:authn_requests_signed] = true
69
- settings.security[:embed_sign] = true
70
- settings.security[:digest_method] = XMLSecurity::Document::SHA256
71
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
72
-
73
- new_settings = OneLogin::RubySaml::Settings.new
74
- assert_equal new_settings.security[:authn_requests_signed], false
75
- assert_equal new_settings.security[:embed_sign], false
76
- assert_equal new_settings.security[:digest_method], XMLSecurity::Document::SHA1
77
- assert_equal new_settings.security[:signature_method], XMLSecurity::Document::RSA_SHA1
78
- end
79
-
80
- it "overrides only provided security attributes passing a second parameter" do
81
- config = {
82
- :security => {
83
- :metadata_signed => true
84
- }
85
- }
86
-
87
- @default_attributes = OneLogin::RubySaml::Settings::DEFAULTS
88
-
89
- @settings = OneLogin::RubySaml::Settings.new(config, true)
90
- assert_equal @settings.security[:metadata_signed], true
91
- assert_equal @settings.security[:digest_method], @default_attributes[:security][:digest_method]
92
- end
93
-
94
- it "doesn't override only provided security attributes without passing a second parameter" do
95
- config = {
96
- :security => {
97
- :metadata_signed => true
98
- }
99
- }
100
-
101
- @default_attributes = OneLogin::RubySaml::Settings::DEFAULTS
102
-
103
- @settings = OneLogin::RubySaml::Settings.new(config)
104
- assert_equal @settings.security[:metadata_signed], true
105
- assert_nil @settings.security[:digest_method]
106
- end
107
-
108
- describe "#single_logout_service_url" do
109
- it "when single_logout_service_url is nil but assertion_consumer_logout_service_url returns its value" do
110
- @settings.single_logout_service_url = nil
111
- @settings.assertion_consumer_logout_service_url = "http://app.muda.no/sls"
112
-
113
- assert_equal "http://app.muda.no/sls", @settings.single_logout_service_url
114
- end
115
- end
116
-
117
- describe "#single_logout_service_binding" do
118
- it "when single_logout_service_binding is nil but assertion_consumer_logout_service_binding returns its value" do
119
- @settings.single_logout_service_binding = nil
120
- @settings.assertion_consumer_logout_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
121
-
122
- assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", @settings.single_logout_service_binding
123
- end
124
- end
125
-
126
- describe "#get_idp_cert" do
127
- it "returns nil when the cert is an empty string" do
128
- @settings.idp_cert = ""
129
- assert_nil @settings.get_idp_cert
130
- end
131
-
132
- it "returns nil when the cert is nil" do
133
- @settings.idp_cert = nil
134
- assert_nil @settings.get_idp_cert
135
- end
136
-
137
- it "returns the certificate when it is valid" do
138
- @settings.idp_cert = ruby_saml_cert_text
139
- assert @settings.get_idp_cert.kind_of? OpenSSL::X509::Certificate
140
- end
141
-
142
- it "raises when the certificate is not valid" do
143
- # formatted but invalid cert
144
- @settings.idp_cert = read_certificate("formatted_certificate")
145
- assert_raises(OpenSSL::X509::CertificateError) {
146
- @settings.get_idp_cert
147
- }
148
- end
149
- end
150
-
151
- describe "#get_idp_cert_multi" do
152
- it "returns nil when the value is empty" do
153
- @settings.idp_cert = {}
154
- assert_nil @settings.get_idp_cert_multi
155
- end
156
-
157
- it "returns nil when the idp_cert_multi is nil or empty" do
158
- @settings.idp_cert_multi = nil
159
- assert_nil @settings.get_idp_cert_multi
160
- end
161
-
162
- it "returns partial hash when contains some values" do
163
- empty_multi = {
164
- :signing => [],
165
- :encryption => []
166
- }
167
-
168
- @settings.idp_cert_multi = {
169
- :signing => []
170
- }
171
- assert_equal empty_multi, @settings.get_idp_cert_multi
172
-
173
- @settings.idp_cert_multi = {
174
- :encryption => []
175
- }
176
- assert_equal empty_multi, @settings.get_idp_cert_multi
177
-
178
- @settings.idp_cert_multi = {
179
- :signing => [],
180
- :encryption => []
181
- }
182
- assert_equal empty_multi, @settings.get_idp_cert_multi
183
-
184
- @settings.idp_cert_multi = {
185
- :yyy => [],
186
- :zzz => []
187
- }
188
- assert_equal empty_multi, @settings.get_idp_cert_multi
189
- end
190
-
191
- it "returns the hash with certificates when values were valid" do
192
- certificates = ruby_saml_cert_text
193
- @settings.idp_cert_multi = {
194
- :signing => [ruby_saml_cert_text],
195
- :encryption => [ruby_saml_cert_text],
196
- }
197
-
198
- assert @settings.get_idp_cert_multi.kind_of? Hash
199
- assert @settings.get_idp_cert_multi[:signing].kind_of? Array
200
- assert @settings.get_idp_cert_multi[:encryption].kind_of? Array
201
- assert @settings.get_idp_cert_multi[:signing][0].kind_of? OpenSSL::X509::Certificate
202
- assert @settings.get_idp_cert_multi[:encryption][0].kind_of? OpenSSL::X509::Certificate
203
- end
204
-
205
- it "raises when there is a cert in idp_cert_multi not valid" do
206
- certificate = read_certificate("formatted_certificate")
207
-
208
- @settings.idp_cert_multi = {
209
- :signing => [],
210
- :encryption => []
211
- }
212
- @settings.idp_cert_multi[:signing].push(certificate)
213
- @settings.idp_cert_multi[:encryption].push(certificate)
214
-
215
- assert_raises(OpenSSL::X509::CertificateError) {
216
- @settings.get_idp_cert_multi
217
- }
218
- end
219
- end
220
-
221
- describe "#get_sp_cert" do
222
- it "returns nil when the cert is an empty string" do
223
- @settings.certificate = ""
224
- assert_nil @settings.get_sp_cert
225
- end
226
-
227
- it "returns nil when the cert is nil" do
228
- @settings.certificate = nil
229
- assert_nil @settings.get_sp_cert
230
- end
231
-
232
- it "returns the certificate when it is valid" do
233
- @settings.certificate = ruby_saml_cert_text
234
- assert @settings.get_sp_cert.kind_of? OpenSSL::X509::Certificate
235
- end
236
-
237
- it "raises when the certificate is not valid" do
238
- # formatted but invalid cert
239
- @settings.certificate = read_certificate("formatted_certificate")
240
- assert_raises(OpenSSL::X509::CertificateError) {
241
- @settings.get_sp_cert
242
- }
243
- end
244
-
245
- end
246
-
247
- describe "#get_sp_cert_new" do
248
- it "returns nil when the cert is an empty string" do
249
- @settings.certificate_new = ""
250
- assert_nil @settings.get_sp_cert_new
251
- end
252
-
253
- it "returns nil when the cert is nil" do
254
- @settings.certificate_new = nil
255
- assert_nil @settings.get_sp_cert_new
256
- end
257
-
258
- it "returns the certificate when it is valid" do
259
- @settings.certificate_new = ruby_saml_cert_text
260
- assert @settings.get_sp_cert_new.kind_of? OpenSSL::X509::Certificate
261
- end
262
-
263
- it "raises when the certificate is not valid" do
264
- # formatted but invalid cert
265
- @settings.certificate_new = read_certificate("formatted_certificate")
266
- assert_raises(OpenSSL::X509::CertificateError) {
267
- @settings.get_sp_cert_new
268
- }
269
- end
270
-
271
- end
272
-
273
- describe "#get_sp_key" do
274
- it "returns nil when the private key is an empty string" do
275
- @settings.private_key = ""
276
- assert_nil @settings.get_sp_key
277
- end
278
-
279
- it "returns nil when the private key is nil" do
280
- @settings.private_key = nil
281
- assert_nil @settings.get_sp_key
282
- end
283
-
284
- it "returns the private key when it is valid" do
285
- @settings.private_key = ruby_saml_key_text
286
- assert @settings.get_sp_key.kind_of? OpenSSL::PKey::RSA
287
- end
288
-
289
- it "raises when the private key is not valid" do
290
- # formatted but invalid rsa private key
291
- @settings.private_key = read_certificate("formatted_rsa_private_key")
292
- assert_raises(OpenSSL::PKey::RSAError) {
293
- @settings.get_sp_key
294
- }
295
- end
296
-
297
- end
298
-
299
- describe "#get_fingerprint" do
300
- it "get the fingerprint value when cert and fingerprint in settings are nil" do
301
- @settings.idp_cert_fingerprint = nil
302
- @settings.idp_cert = nil
303
- fingerprint = @settings.get_fingerprint
304
- assert_nil fingerprint
305
- end
306
-
307
- it "get the fingerprint value when there is a cert at the settings" do
308
- @settings.idp_cert_fingerprint = nil
309
- @settings.idp_cert = ruby_saml_cert_text
310
- fingerprint = @settings.get_fingerprint
311
- assert fingerprint.downcase == ruby_saml_cert_fingerprint.downcase
312
- end
313
-
314
- it "get the fingerprint value when there is a fingerprint at the settings" do
315
- @settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
316
- @settings.idp_cert = nil
317
- fingerprint = @settings.get_fingerprint
318
- assert fingerprint.downcase == ruby_saml_cert_fingerprint.downcase
319
- end
320
-
321
- it "get the fingerprint value when there are cert and fingerprint at the settings" do
322
- @settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
323
- @settings.idp_cert = ruby_saml_cert_text
324
- fingerprint = @settings.get_fingerprint
325
- assert fingerprint.downcase == ruby_saml_cert_fingerprint.downcase
326
- end
327
- end
328
- end
329
- end
@@ -1,448 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
- require 'logout_responses/logoutresponse_fixtures'
3
-
4
- require 'onelogin/ruby-saml/slo_logoutrequest'
5
- require 'timecop'
6
-
7
- class RubySamlTest < Minitest::Test
8
-
9
- describe "SloLogoutrequest" do
10
-
11
- let(:settings) { OneLogin::RubySaml::Settings.new }
12
- let(:logout_request) { OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document) }
13
- let(:invalid_logout_request) { OneLogin::RubySaml::SloLogoutrequest.new(invalid_logout_request_document) }
14
-
15
- before do
16
- settings.idp_entity_id = 'https://app.onelogin.com/saml/metadata/SOMEACCOUNT'
17
- settings.soft = true
18
- logout_request.settings = settings
19
- invalid_logout_request.settings = settings
20
- end
21
-
22
- describe "initiator" do
23
- it "raise an exception when logout request is initialized with nil" do
24
- assert_raises(ArgumentError) { OneLogin::RubySaml::SloLogoutrequest.new(nil) }
25
- end
26
- end
27
-
28
- describe "#is_valid?" do
29
- it "return false when logout request is initialized with blank data" do
30
- logout_request_blank = OneLogin::RubySaml::SloLogoutrequest.new('')
31
- assert !logout_request_blank.is_valid?
32
- assert_includes logout_request_blank.errors, 'Blank logout request'
33
- end
34
-
35
- it "return true when the logout request is initialized with valid data" do
36
- assert logout_request.is_valid?
37
- assert_empty logout_request.errors
38
- assert_equal 'someone@example.org', logout_request.nameid
39
- end
40
-
41
- it "should be idempotent when the logout request is initialized with invalid data" do
42
- assert !invalid_logout_request.is_valid?
43
- assert_equal ['Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd'], invalid_logout_request.errors
44
- assert !invalid_logout_request.is_valid?
45
- assert_equal ['Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd'], invalid_logout_request.errors
46
- end
47
-
48
- it "should be idempotent when the logout request is initialized with valid data" do
49
- assert logout_request.is_valid?
50
- assert_empty logout_request.errors
51
- assert logout_request.is_valid?
52
- assert_empty logout_request.errors
53
- end
54
-
55
- it "collect errors when collect_errors=true" do
56
- settings.idp_entity_id = 'http://idp.example.com/invalid'
57
- settings.idp_slo_target_url = "http://example.com?field=value"
58
- settings.security[:logout_requests_signed] = true
59
- settings.security[:embed_sign] = false
60
- settings.certificate = ruby_saml_cert_text
61
- settings.private_key = ruby_saml_key_text
62
- settings.idp_cert = ruby_saml_cert_text
63
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
64
- params = {}
65
- params['SAMLRequest'] = logout_request_deflated_base64
66
- params['RelayState'] = 'http://invalid.example.com'
67
- params['Signature'] = 'invalid_signature'
68
- params['SigAlg'] = XMLSecurity::Document::RSA_SHA1
69
- options = {}
70
- options[:get_params] = params
71
-
72
- logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
73
- logout_request_sign_test.settings = settings
74
-
75
- collect_errors = true
76
- assert !logout_request_sign_test.is_valid?(collect_errors)
77
- assert_includes logout_request_sign_test.errors, "Invalid Signature on Logout Request"
78
- assert_includes logout_request_sign_test.errors, "Doesn't match the issuer, expected: <http://idp.example.com/invalid>, but was: <https://app.onelogin.com/saml/metadata/SOMEACCOUNT>"
79
- end
80
-
81
- it "raise error for invalid xml" do
82
- invalid_logout_request.soft = false
83
- assert_raises(OneLogin::RubySaml::ValidationError) { invalid_logout_request.is_valid? }
84
- end
85
-
86
- end
87
-
88
- describe "#nameid" do
89
- it "extract the value of the name id element" do
90
- assert_equal "someone@example.org", logout_request.nameid
91
- end
92
- end
93
-
94
- describe "#nameid_format" do
95
- let(:logout_request) { OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document_with_name_id_format) }
96
-
97
- it "extract the format attribute of the name id element" do
98
- assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", logout_request.nameid_format
99
- end
100
- end
101
-
102
- describe "#issuer" do
103
- it "return the issuer inside the logout request" do
104
- assert_equal "https://app.onelogin.com/saml/metadata/SOMEACCOUNT", logout_request.issuer
105
- end
106
- end
107
-
108
- describe "#id" do
109
- it "extract the value of the ID attribute" do
110
- assert_equal "_c0348950-935b-0131-1060-782bcb56fcaa", logout_request.id
111
- end
112
- end
113
-
114
- describe "#not_on_or_after" do
115
- it "extract the value of the NotOnOrAfter attribute" do
116
- time_value = '2014-07-17T01:01:48Z'
117
- assert_nil logout_request.not_on_or_after
118
- logout_request.document.root.attributes['NotOnOrAfter'] = time_value
119
- assert_equal Time.parse(time_value), logout_request.not_on_or_after
120
- end
121
- end
122
-
123
- describe '#session_indexes' do
124
- it "return empty array when no SessionIndex" do
125
- assert_equal [], logout_request.session_indexes
126
- end
127
-
128
- it "return an Array with one SessionIndex" do
129
- logout_request_with_session_index = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_xml_with_session_index)
130
- assert_equal ['_ea853497-c58a-408a-bc23-c849752d9741'], logout_request_with_session_index.session_indexes
131
- end
132
- end
133
-
134
- describe "#validate_id" do
135
- it "return true when there is a valid ID in the logout request" do
136
- assert logout_request.send(:validate_id)
137
- assert_empty logout_request.errors
138
- end
139
-
140
- it "return false when there is an invalid ID in the logout request" do
141
- logout_request_blank = OneLogin::RubySaml::SloLogoutrequest.new('')
142
- assert !logout_request_blank.send(:validate_id)
143
- assert_includes logout_request_blank.errors, "Missing ID attribute on Logout Request"
144
- end
145
- end
146
-
147
- describe "#validate_version" do
148
- it "return true when the logout request is SAML 2.0 Version" do
149
- assert logout_request.send(:validate_version)
150
- end
151
-
152
- it "return false when the logout request is not SAML 2.0 Version" do
153
- logout_request_blank = OneLogin::RubySaml::SloLogoutrequest.new('')
154
- assert !logout_request_blank.send(:validate_version)
155
- assert_includes logout_request_blank.errors, "Unsupported SAML version"
156
- end
157
- end
158
-
159
- describe "#validate_not_on_or_after" do
160
- it "return true when the logout request has a valid NotOnOrAfter or does not contain any" do
161
- assert logout_request.send(:validate_not_on_or_after)
162
- assert_empty logout_request.errors
163
- Timecop.freeze Time.parse('2011-06-14T18:25:01.516Z') do
164
- time_value = '2014-07-17T01:01:48Z'
165
- logout_request.document.root.attributes['NotOnOrAfter'] = time_value
166
- assert logout_request.send(:validate_not_on_or_after)
167
- assert_empty logout_request.errors
168
- end
169
- end
170
-
171
- it "return false when the logout request has an invalid NotOnOrAfter" do
172
- logout_request.document.root.attributes['NotOnOrAfter'] = '2014-07-17T01:01:48Z'
173
- assert !logout_request.send(:validate_not_on_or_after)
174
- assert /Current time is on or after NotOnOrAfter/.match(logout_request.errors[0])
175
- end
176
-
177
- it "raise when the logout request has an invalid NotOnOrAfter" do
178
- logout_request.document.root.attributes['NotOnOrAfter'] = '2014-07-17T01:01:48Z'
179
- logout_request.soft = false
180
- assert_raises(OneLogin::RubySaml::ValidationError, "Current time is on or after NotOnOrAfter") do
181
- logout_request.send(:validate_not_on_or_after)
182
- end
183
- end
184
- end
185
-
186
- describe "#validate_request_state" do
187
- it "return true when valid logout request xml" do
188
- assert logout_request.send(:validate_request_state)
189
- assert_empty logout_request.errors
190
- assert logout_request.send(:validate_request_state)
191
- assert_empty logout_request.errors
192
- end
193
-
194
- it "return false when invalid logout request xml" do
195
- logout_request_blank = OneLogin::RubySaml::SloLogoutrequest.new('')
196
- logout_request_blank.soft = true
197
- assert !logout_request_blank.send(:validate_request_state)
198
- assert_includes logout_request_blank.errors, "Blank logout request"
199
- end
200
-
201
- it "raise error for invalid xml" do
202
- logout_request_blank = OneLogin::RubySaml::SloLogoutrequest.new('')
203
- logout_request_blank.soft = false
204
- assert_raises(OneLogin::RubySaml::ValidationError, "Blank logout request") do
205
- logout_request_blank.send(:validate_request_state)
206
- end
207
- end
208
- end
209
-
210
- describe "#validate_structure" do
211
- it "return true when encountering a valid Logout Request xml" do
212
- assert logout_request.send(:validate_structure)
213
- assert_empty logout_request.errors
214
- end
215
-
216
- it "return false when encountering a Logout Request bad formatted" do
217
- assert !invalid_logout_request.send(:validate_structure)
218
- assert_includes invalid_logout_request.errors, "Invalid SAML Logout Request. Not match the saml-schema-protocol-2.0.xsd"
219
- end
220
-
221
- it "raise when encountering a Logout Request bad formatted" do
222
- invalid_logout_request.soft = false
223
- assert_raises(OneLogin::RubySaml::ValidationError, "Element '{urn:oasis:names:tc:SAML:2.0:assertion}Issuer': This element is not expected") do
224
- invalid_logout_request.send(:validate_structure)
225
- end
226
- end
227
- end
228
-
229
- describe "#validate_issuer" do
230
- it "return true when the issuer of the Logout Request matchs the IdP entityId" do
231
- logout_request.settings.idp_entity_id = 'https://app.onelogin.com/saml/metadata/SOMEACCOUNT'
232
- assert logout_request.send(:validate_issuer)
233
- end
234
- it "return false when the issuer of the Logout Request does not match the IdP entityId" do
235
- logout_request.settings.idp_entity_id = 'http://idp.example.com/invalid'
236
- assert !logout_request.send(:validate_issuer)
237
- assert_includes logout_request.errors, "Doesn't match the issuer, expected: <#{logout_request.settings.idp_entity_id}>, but was: <https://app.onelogin.com/saml/metadata/SOMEACCOUNT>"
238
- end
239
- it "raise when the issuer of the Logout Request does not match the IdP entityId" do
240
- logout_request.settings.idp_entity_id = 'http://idp.example.com/invalid'
241
- logout_request.soft = false
242
- assert_raises(OneLogin::RubySaml::ValidationError, "Doesn't match the issuer, expected: <#{logout_request.settings.idp_entity_id}>, but was: <https://app.onelogin.com/saml/metadata/SOMEACCOUNT>") do
243
- logout_request.send(:validate_issuer)
244
- end
245
- end
246
- end
247
-
248
- describe "#validate_signature" do
249
- before do
250
- settings.idp_slo_target_url = "http://example.com?field=value"
251
- settings.security[:logout_requests_signed] = true
252
- settings.security[:embed_sign] = false
253
- settings.certificate = ruby_saml_cert_text
254
- settings.private_key = ruby_saml_key_text
255
- settings.idp_cert = ruby_saml_cert_text
256
- end
257
-
258
- it "return true when no idp_cert is provided and option :relax_signature_validation is present" do
259
- settings.idp_cert = nil
260
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
261
- params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
262
- params['RelayState'] = params[:RelayState]
263
- options = {}
264
- options[:get_params] = params
265
- options[:relax_signature_validation] = true
266
- logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
267
- logout_request_sign_test.settings = settings
268
- assert logout_request_sign_test.send(:validate_signature)
269
- end
270
-
271
- it "return false when no idp_cert is provided and no option :relax_signature_validation is present" do
272
- settings.idp_cert = nil
273
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
274
- params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
275
- params['RelayState'] = params[:RelayState]
276
- options = {}
277
- options[:get_params] = params
278
- logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
279
- logout_request_sign_test.settings = settings
280
- assert !logout_request_sign_test.send(:validate_signature)
281
- end
282
-
283
- it "return true when valid RSA_SHA1 Signature" do
284
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
285
- params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
286
- params['RelayState'] = params[:RelayState]
287
- options = {}
288
- options[:get_params] = params
289
- logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
290
- logout_request_sign_test.settings = settings
291
- assert logout_request_sign_test.send(:validate_signature)
292
- end
293
-
294
- it "return true when valid RSA_SHA256 Signature" do
295
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
296
- params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
297
- options = {}
298
- options[:get_params] = params
299
- logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
300
- params['RelayState'] = params[:RelayState]
301
- logout_request_sign_test.settings = settings
302
- assert logout_request_sign_test.send(:validate_signature)
303
- end
304
-
305
- it "return false when invalid RSA_SHA1 Signature" do
306
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
307
- params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
308
- params['RelayState'] = 'http://invalid.example.com'
309
- params[:RelayState] = params['RelayState']
310
- options = {}
311
- options[:get_params] = params
312
-
313
- logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
314
- logout_request_sign_test.settings = settings
315
- assert !logout_request_sign_test.send(:validate_signature)
316
- end
317
-
318
- it "raise when invalid RSA_SHA1 Signature" do
319
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
320
- settings.soft = false
321
- params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
322
- params['RelayState'] = 'http://invalid.example.com'
323
- params[:RelayState] = params['RelayState']
324
- options = {}
325
- options[:get_params] = params
326
- options[:settings] = settings
327
-
328
- logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
329
- assert_raises(OneLogin::RubySaml::ValidationError, "Invalid Signature on Logout Request") do
330
- logout_request_sign_test.send(:validate_signature)
331
- end
332
- end
333
-
334
- it "raise when get_params encoding differs from what this library generates" do
335
- # Use Logoutrequest only to build the SAMLRequest parameter.
336
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
337
- settings.soft = false
338
- params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, "RelayState" => "http://example.com")
339
- # Assemble query string.
340
- query = OneLogin::RubySaml::Utils.build_query(
341
- :type => 'SAMLRequest',
342
- :data => params['SAMLRequest'],
343
- :relay_state => params['RelayState'],
344
- :sig_alg => params['SigAlg']
345
- )
346
- # Modify the query string so that it encodes the same values,
347
- # but with different percent-encoding. Sanity-check that they
348
- # really are equialent before moving on.
349
- original_query = query.dup
350
- query.gsub!("example", "ex%61mple")
351
- refute_equal(query, original_query)
352
- assert_equal(CGI.unescape(query), CGI.unescape(original_query))
353
- # Make normalised signature based on our modified params.
354
- sign_algorithm = XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method])
355
- signature = settings.get_sp_key.sign(sign_algorithm.new, query)
356
- params['Signature'] = Base64.encode64(signature).gsub(/\n/, "")
357
- # Construct SloLogoutrequest and ask it to validate the signature.
358
- # It will do it incorrectly, because it will compute it based on re-encoded
359
- # query parameters, rather than their original encodings.
360
- options = {}
361
- options[:get_params] = params
362
- options[:settings] = settings
363
- logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
364
- assert_raises(OneLogin::RubySaml::ValidationError, "Invalid Signature on Logout Request") do
365
- logout_request_sign_test.send(:validate_signature)
366
- end
367
- end
368
-
369
- it "return true even if raw_get_params encoding differs from what this library generates" do
370
- # Use Logoutrequest only to build the SAMLRequest parameter.
371
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
372
- settings.soft = false
373
- params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, "RelayState" => "http://example.com")
374
- # Assemble query string.
375
- query = OneLogin::RubySaml::Utils.build_query(
376
- :type => 'SAMLRequest',
377
- :data => params['SAMLRequest'],
378
- :relay_state => params['RelayState'],
379
- :sig_alg => params['SigAlg']
380
- )
381
- # Modify the query string so that it encodes the same values,
382
- # but with different percent-encoding. Sanity-check that they
383
- # really are equialent before moving on.
384
- original_query = query.dup
385
- query.gsub!("example", "ex%61mple")
386
- refute_equal(query, original_query)
387
- assert_equal(CGI.unescape(query), CGI.unescape(original_query))
388
- # Make normalised signature based on our modified params.
389
- sign_algorithm = XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method])
390
- signature = settings.get_sp_key.sign(sign_algorithm.new, query)
391
- params['Signature'] = Base64.encode64(signature).gsub(/\n/, "")
392
- # Construct SloLogoutrequest and ask it to validate the signature.
393
- # Provide the altered parameter in its raw URI-encoded form,
394
- # so that we don't have to guess the value that contributed to the signature.
395
- options = {}
396
- options[:get_params] = params
397
- options[:get_params].delete("RelayState")
398
- options[:raw_get_params] = {
399
- "RelayState" => "http%3A%2F%2Fex%61mple.com",
400
- }
401
- options[:settings] = settings
402
- logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
403
- assert logout_request_sign_test.send(:validate_signature)
404
- end
405
- end
406
-
407
- describe "#validate_signature with multiple idp certs" do
408
- before do
409
- settings.idp_slo_target_url = "http://example.com?field=value"
410
- settings.certificate = ruby_saml_cert_text
411
- settings.private_key = ruby_saml_key_text
412
- settings.idp_cert = nil
413
- settings.security[:logout_requests_signed] = true
414
- settings.security[:embed_sign] = false
415
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
416
- end
417
-
418
- it "return true when at least a idp_cert is valid" do
419
- params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
420
- params['RelayState'] = params[:RelayState]
421
- options = {}
422
- options[:get_params] = params
423
- logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
424
- settings.idp_cert_multi = {
425
- :signing => [ruby_saml_cert_text2, ruby_saml_cert_text],
426
- :encryption => []
427
- }
428
- logout_request_sign_test.settings = settings
429
- assert logout_request_sign_test.send(:validate_signature)
430
- end
431
-
432
- it "return false when none cert on idp_cert_multi is valid" do
433
- params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
434
- params['RelayState'] = params[:RelayState]
435
- options = {}
436
- options[:get_params] = params
437
- logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
438
- settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
439
- settings.idp_cert_multi = {
440
- :signing => [ruby_saml_cert_text2, ruby_saml_cert_text2],
441
- :encryption => []
442
- }
443
- logout_request_sign_test.settings = settings
444
- assert !logout_request_sign_test.send(:validate_signature)
445
- end
446
- end
447
- end
448
- end