ruby-saml 1.8.0 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/test.yml +25 -0
  3. data/{changelog.md → CHANGELOG.md} +66 -1
  4. data/README.md +365 -209
  5. data/UPGRADING.md +149 -0
  6. data/lib/onelogin/ruby-saml/attribute_service.rb +1 -1
  7. data/lib/onelogin/ruby-saml/attributes.rb +24 -1
  8. data/lib/onelogin/ruby-saml/authrequest.rb +25 -9
  9. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +285 -184
  10. data/lib/onelogin/ruby-saml/logging.rb +4 -1
  11. data/lib/onelogin/ruby-saml/logoutrequest.rb +25 -10
  12. data/lib/onelogin/ruby-saml/logoutresponse.rb +33 -17
  13. data/lib/onelogin/ruby-saml/metadata.rb +62 -17
  14. data/lib/onelogin/ruby-saml/response.rb +89 -45
  15. data/lib/onelogin/ruby-saml/saml_message.rb +17 -8
  16. data/lib/onelogin/ruby-saml/setting_error.rb +6 -0
  17. data/lib/onelogin/ruby-saml/settings.rb +124 -43
  18. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +38 -11
  19. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +42 -19
  20. data/lib/onelogin/ruby-saml/utils.rb +94 -12
  21. data/lib/onelogin/ruby-saml/version.rb +1 -1
  22. data/lib/xml_security.rb +44 -19
  23. data/ruby-saml.gemspec +16 -8
  24. metadata +44 -282
  25. data/.travis.yml +0 -26
  26. data/test/certificates/certificate1 +0 -12
  27. data/test/certificates/certificate_without_head_foot +0 -1
  28. data/test/certificates/formatted_certificate +0 -14
  29. data/test/certificates/formatted_chained_certificate +0 -42
  30. data/test/certificates/formatted_private_key +0 -12
  31. data/test/certificates/formatted_rsa_private_key +0 -12
  32. data/test/certificates/invalid_certificate1 +0 -1
  33. data/test/certificates/invalid_certificate2 +0 -1
  34. data/test/certificates/invalid_certificate3 +0 -12
  35. data/test/certificates/invalid_chained_certificate1 +0 -1
  36. data/test/certificates/invalid_private_key1 +0 -1
  37. data/test/certificates/invalid_private_key2 +0 -1
  38. data/test/certificates/invalid_private_key3 +0 -10
  39. data/test/certificates/invalid_rsa_private_key1 +0 -1
  40. data/test/certificates/invalid_rsa_private_key2 +0 -1
  41. data/test/certificates/invalid_rsa_private_key3 +0 -10
  42. data/test/certificates/ruby-saml-2.crt +0 -15
  43. data/test/certificates/ruby-saml.crt +0 -14
  44. data/test/certificates/ruby-saml.key +0 -15
  45. data/test/idp_metadata_parser_test.rb +0 -579
  46. data/test/logging_test.rb +0 -62
  47. data/test/logout_requests/invalid_slo_request.xml +0 -6
  48. data/test/logout_requests/slo_request.xml +0 -4
  49. data/test/logout_requests/slo_request.xml.base64 +0 -1
  50. data/test/logout_requests/slo_request_deflated.xml.base64 +0 -1
  51. data/test/logout_requests/slo_request_with_name_id_format.xml +0 -4
  52. data/test/logout_requests/slo_request_with_session_index.xml +0 -5
  53. data/test/logout_responses/logoutresponse_fixtures.rb +0 -67
  54. data/test/logoutrequest_test.rb +0 -226
  55. data/test/logoutresponse_test.rb +0 -402
  56. data/test/metadata/idp_descriptor.xml +0 -26
  57. data/test/metadata/idp_descriptor_2.xml +0 -56
  58. data/test/metadata/idp_descriptor_3.xml +0 -14
  59. data/test/metadata/idp_descriptor_4.xml +0 -72
  60. data/test/metadata/idp_metadata_different_sign_and_encrypt_cert.xml +0 -72
  61. data/test/metadata/idp_metadata_multi_certs.xml +0 -75
  62. data/test/metadata/idp_metadata_multi_signing_certs.xml +0 -52
  63. data/test/metadata/idp_metadata_same_sign_and_encrypt_cert.xml +0 -71
  64. data/test/metadata/idp_multiple_descriptors.xml +0 -53
  65. data/test/metadata/no_idp_descriptor.xml +0 -21
  66. data/test/metadata_test.rb +0 -331
  67. data/test/request_test.rb +0 -323
  68. data/test/response_test.rb +0 -1586
  69. data/test/responses/adfs_response_sha1.xml +0 -46
  70. data/test/responses/adfs_response_sha256.xml +0 -46
  71. data/test/responses/adfs_response_sha384.xml +0 -46
  72. data/test/responses/adfs_response_sha512.xml +0 -46
  73. data/test/responses/adfs_response_xmlns.xml +0 -45
  74. data/test/responses/attackxee.xml +0 -13
  75. data/test/responses/invalids/duplicated_attributes.xml.base64 +0 -1
  76. data/test/responses/invalids/empty_destination.xml.base64 +0 -1
  77. data/test/responses/invalids/empty_nameid.xml.base64 +0 -1
  78. data/test/responses/invalids/encrypted_new_attack.xml.base64 +0 -1
  79. data/test/responses/invalids/invalid_audience.xml.base64 +0 -1
  80. data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
  81. data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
  82. data/test/responses/invalids/invalid_signature_position.xml.base64 +0 -1
  83. data/test/responses/invalids/invalid_subjectconfirmation_inresponse.xml.base64 +0 -1
  84. data/test/responses/invalids/invalid_subjectconfirmation_nb.xml.base64 +0 -1
  85. data/test/responses/invalids/invalid_subjectconfirmation_noa.xml.base64 +0 -1
  86. data/test/responses/invalids/invalid_subjectconfirmation_recipient.xml.base64 +0 -1
  87. data/test/responses/invalids/multiple_assertions.xml.base64 +0 -2
  88. data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
  89. data/test/responses/invalids/no_authnstatement.xml.base64 +0 -1
  90. data/test/responses/invalids/no_conditions.xml.base64 +0 -1
  91. data/test/responses/invalids/no_id.xml.base64 +0 -1
  92. data/test/responses/invalids/no_issuer_assertion.xml.base64 +0 -1
  93. data/test/responses/invalids/no_issuer_response.xml.base64 +0 -1
  94. data/test/responses/invalids/no_nameid.xml.base64 +0 -1
  95. data/test/responses/invalids/no_saml2.xml.base64 +0 -1
  96. data/test/responses/invalids/no_signature.xml.base64 +0 -1
  97. data/test/responses/invalids/no_status.xml.base64 +0 -1
  98. data/test/responses/invalids/no_status_code.xml.base64 +0 -1
  99. data/test/responses/invalids/no_subjectconfirmation_data.xml.base64 +0 -1
  100. data/test/responses/invalids/no_subjectconfirmation_method.xml.base64 +0 -1
  101. data/test/responses/invalids/response_invalid_signed_element.xml.base64 +0 -1
  102. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
  103. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
  104. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
  105. data/test/responses/invalids/status_code_responder.xml.base64 +0 -1
  106. data/test/responses/invalids/status_code_responer_and_msg.xml.base64 +0 -1
  107. data/test/responses/invalids/wrong_spnamequalifier.xml.base64 +0 -1
  108. data/test/responses/no_signature_ns.xml +0 -48
  109. data/test/responses/open_saml_response.xml +0 -56
  110. data/test/responses/response_assertion_wrapped.xml.base64 +0 -93
  111. data/test/responses/response_audience_self_closed_tag.xml.base64 +0 -1
  112. data/test/responses/response_double_status_code.xml.base64 +0 -1
  113. data/test/responses/response_encrypted_attrs.xml.base64 +0 -1
  114. data/test/responses/response_encrypted_nameid.xml.base64 +0 -1
  115. data/test/responses/response_eval.xml +0 -7
  116. data/test/responses/response_no_cert_and_encrypted_attrs.xml +0 -29
  117. data/test/responses/response_node_text_attack.xml.base64 +0 -1
  118. data/test/responses/response_node_text_attack2.xml.base64 +0 -1
  119. data/test/responses/response_node_text_attack3.xml.base64 +0 -1
  120. data/test/responses/response_unsigned_xml_base64 +0 -1
  121. data/test/responses/response_with_ampersands.xml +0 -139
  122. data/test/responses/response_with_ampersands.xml.base64 +0 -93
  123. data/test/responses/response_with_ds_namespace_at_the_root.xml.base64 +0 -1
  124. data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
  125. data/test/responses/response_with_multiple_attribute_values.xml +0 -67
  126. data/test/responses/response_with_retrieval_method.xml +0 -26
  127. data/test/responses/response_with_saml2_namespace.xml.base64 +0 -102
  128. data/test/responses/response_with_signed_assertion.xml.base64 +0 -66
  129. data/test/responses/response_with_signed_assertion_2.xml.base64 +0 -1
  130. data/test/responses/response_with_signed_assertion_3.xml +0 -30
  131. data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
  132. data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
  133. data/test/responses/response_without_attributes.xml.base64 +0 -79
  134. data/test/responses/response_without_reference_uri.xml.base64 +0 -1
  135. data/test/responses/response_wrapped.xml.base64 +0 -150
  136. data/test/responses/signed_message_encrypted_signed_assertion.xml.base64 +0 -1
  137. data/test/responses/signed_message_encrypted_unsigned_assertion.xml.base64 +0 -1
  138. data/test/responses/signed_nameid_in_atts.xml +0 -47
  139. data/test/responses/signed_unqual_nameid_in_atts.xml +0 -47
  140. data/test/responses/simple_saml_php.xml +0 -71
  141. data/test/responses/starfield_response.xml.base64 +0 -1
  142. data/test/responses/test_sign.xml +0 -43
  143. data/test/responses/unsigned_encrypted_adfs.xml +0 -23
  144. data/test/responses/unsigned_message_aes128_encrypted_signed_assertion.xml.base64 +0 -1
  145. data/test/responses/unsigned_message_aes192_encrypted_signed_assertion.xml.base64 +0 -1
  146. data/test/responses/unsigned_message_aes256_encrypted_signed_assertion.xml.base64 +0 -1
  147. data/test/responses/unsigned_message_des192_encrypted_signed_assertion.xml.base64 +0 -1
  148. data/test/responses/unsigned_message_encrypted_assertion_without_saml_namespace.xml.base64 +0 -1
  149. data/test/responses/unsigned_message_encrypted_signed_assertion.xml.base64 +0 -1
  150. data/test/responses/unsigned_message_encrypted_unsigned_assertion.xml.base64 +0 -1
  151. data/test/responses/valid_response.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 -301
  155. data/test/slo_logoutrequest_test.rb +0 -448
  156. data/test/slo_logoutresponse_test.rb +0 -199
  157. data/test/test_helper.rb +0 -327
  158. data/test/utils_test.rb +0 -254
  159. data/test/xml_security_test.rb +0 -421
@@ -1,331 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
-
3
- require 'onelogin/ruby-saml/metadata'
4
-
5
- class MetadataTest < Minitest::Test
6
-
7
- describe 'Metadata' do
8
- let(:settings) { OneLogin::RubySaml::Settings.new }
9
- let(:xml_text) { OneLogin::RubySaml::Metadata.new.generate(settings, false) }
10
- let(:xml_doc) { REXML::Document.new(xml_text) }
11
- let(:spsso_descriptor) { REXML::XPath.first(xml_doc, "//md:SPSSODescriptor") }
12
- let(:acs) { REXML::XPath.first(xml_doc, "//md:AssertionConsumerService") }
13
-
14
- before do
15
- settings.issuer = "https://example.com"
16
- settings.name_identifier_format = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
17
- settings.assertion_consumer_service_url = "https://foo.example/saml/consume"
18
- end
19
-
20
- it "generates Pretty Print Service Provider Metadata" do
21
- xml_text = OneLogin::RubySaml::Metadata.new.generate(settings, true)
22
- # assert correct xml declaration
23
- start = "<?xml version='1.0' encoding='UTF-8'?>\n<md:EntityDescriptor"
24
- assert_equal xml_text[0..start.length-1],start
25
-
26
- assert_equal "https://example.com", REXML::XPath.first(xml_doc, "//md:EntityDescriptor").attribute("entityID").value
27
-
28
- assert_equal "urn:oasis:names:tc:SAML:2.0:protocol", spsso_descriptor.attribute("protocolSupportEnumeration").value
29
- assert_equal "false", spsso_descriptor.attribute("AuthnRequestsSigned").value
30
- assert_equal "false", spsso_descriptor.attribute("WantAssertionsSigned").value
31
-
32
- assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", REXML::XPath.first(xml_doc, "//md:NameIDFormat").text.strip
33
-
34
- assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", acs.attribute("Binding").value
35
- assert_equal "https://foo.example/saml/consume", acs.attribute("Location").value
36
-
37
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
38
- end
39
-
40
- it "generates Service Provider Metadata" do
41
- settings.single_logout_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"
42
- settings.single_logout_service_url = "https://foo.example/saml/sls"
43
- xml_metadata = OneLogin::RubySaml::Metadata.new.generate(settings, false)
44
-
45
- start = "<?xml version='1.0' encoding='UTF-8'?><md:EntityDescriptor"
46
- assert_equal xml_metadata[0..start.length-1],start
47
-
48
- doc_metadata = REXML::Document.new(xml_metadata)
49
- sls = REXML::XPath.first(doc_metadata, "//md:SingleLogoutService")
50
-
51
- assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect", sls.attribute("Binding").value
52
- assert_equal "https://foo.example/saml/sls", sls.attribute("Location").value
53
- assert_equal "https://foo.example/saml/sls", sls.attribute("ResponseLocation").value
54
- assert_nil sls.attribute("isDefault")
55
- assert_nil sls.attribute("index")
56
-
57
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
58
- end
59
-
60
- it "generates Service Provider Metadata with single logout service" do
61
- start = "<?xml version='1.0' encoding='UTF-8'?><md:EntityDescriptor"
62
- assert_equal xml_text[0..start.length-1], start
63
-
64
- assert_equal "https://example.com", REXML::XPath.first(xml_doc, "//md:EntityDescriptor").attribute("entityID").value
65
-
66
- assert_equal "urn:oasis:names:tc:SAML:2.0:protocol", spsso_descriptor.attribute("protocolSupportEnumeration").value
67
- assert_equal "false", spsso_descriptor.attribute("AuthnRequestsSigned").value
68
- assert_equal "false", spsso_descriptor.attribute("WantAssertionsSigned").value
69
-
70
- assert_equal "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress", REXML::XPath.first(xml_doc, "//md:NameIDFormat").text.strip
71
-
72
- assert_equal "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST", acs.attribute("Binding").value
73
- assert_equal "https://foo.example/saml/consume", acs.attribute("Location").value
74
-
75
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
76
- end
77
-
78
- describe "WantAssertionsSigned" do
79
- it "generates Service Provider Metadata with WantAssertionsSigned = false" do
80
- settings.security[:want_assertions_signed] = false
81
- assert_equal "false", spsso_descriptor.attribute("WantAssertionsSigned").value
82
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
83
- end
84
-
85
- it "generates Service Provider Metadata with WantAssertionsSigned = true" do
86
- settings.security[:want_assertions_signed] = true
87
- assert_equal "true", spsso_descriptor.attribute("WantAssertionsSigned").value
88
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
89
- end
90
- end
91
-
92
- describe "with a sign/encrypt certificate" do
93
- let(:key_descriptors) do
94
- REXML::XPath.match(
95
- xml_doc,
96
- "//md:KeyDescriptor",
97
- "md" => "urn:oasis:names:tc:SAML:2.0:metadata"
98
- )
99
- end
100
- let(:cert_nodes) do
101
- REXML::XPath.match(
102
- xml_doc,
103
- "//md:KeyDescriptor/ds:KeyInfo/ds:X509Data/ds:X509Certificate",
104
- "md" => "urn:oasis:names:tc:SAML:2.0:metadata",
105
- "ds" => "http://www.w3.org/2000/09/xmldsig#"
106
- )
107
- end
108
- let(:cert) { OpenSSL::X509::Certificate.new(Base64.decode64(cert_nodes[0].text)) }
109
-
110
- before do
111
- settings.certificate = ruby_saml_cert_text
112
- end
113
-
114
- it "generates Service Provider Metadata with X509Certificate for sign" do
115
- assert_equal 1, key_descriptors.length
116
- assert_equal "signing", key_descriptors[0].attribute("use").value
117
-
118
- assert_equal 1, cert_nodes.length
119
- assert_equal ruby_saml_cert.to_der, cert.to_der
120
-
121
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
122
- end
123
-
124
- describe "and signed authentication requests" do
125
- before do
126
- settings.security[:authn_requests_signed] = true
127
- end
128
-
129
- it "generates Service Provider Metadata with AuthnRequestsSigned" do
130
- assert_equal "true", spsso_descriptor.attribute("AuthnRequestsSigned").value
131
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
132
- end
133
- end
134
-
135
- describe "and encrypted assertions" do
136
- before do
137
- settings.security[:want_assertions_encrypted] = true
138
- end
139
-
140
- it "generates Service Provider Metadata with X509Certificate for encrypt" do
141
- assert_equal 2, key_descriptors.length
142
-
143
- assert_equal "encryption", key_descriptors[1].attribute("use").value
144
-
145
- assert_equal 2, cert_nodes.length
146
- assert_equal cert_nodes[0].text, cert_nodes[1].text
147
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
148
- end
149
- end
150
- end
151
-
152
- describe "with a future SP certificate" do
153
- let(:key_descriptors) do
154
- REXML::XPath.match(
155
- xml_doc,
156
- "//md:KeyDescriptor",
157
- "md" => "urn:oasis:names:tc:SAML:2.0:metadata"
158
- )
159
- end
160
- let(:cert_nodes) do
161
- REXML::XPath.match(
162
- xml_doc,
163
- "//md:KeyDescriptor/ds:KeyInfo/ds:X509Data/ds:X509Certificate",
164
- "md" => "urn:oasis:names:tc:SAML:2.0:metadata",
165
- "ds" => "http://www.w3.org/2000/09/xmldsig#"
166
- )
167
- end
168
-
169
- before do
170
- settings.certificate = ruby_saml_cert_text
171
- settings.certificate_new = ruby_saml_cert_text2
172
- end
173
-
174
- it "generates Service Provider Metadata with 2 X509Certificate for sign" do
175
- assert_equal 2, key_descriptors.length
176
- assert_equal "signing", key_descriptors[0].attribute("use").value
177
- assert_equal "signing", key_descriptors[1].attribute("use").value
178
-
179
- cert = OpenSSL::X509::Certificate.new(Base64.decode64(cert_nodes[0].text))
180
- cert_new = OpenSSL::X509::Certificate.new(Base64.decode64(cert_nodes[1].text))
181
-
182
- assert_equal 2, cert_nodes.length
183
- assert_equal ruby_saml_cert.to_der, cert.to_der
184
- assert_equal ruby_saml_cert2.to_der, cert_new.to_der
185
-
186
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
187
- end
188
-
189
- describe "and signed authentication requests" do
190
- before do
191
- settings.security[:authn_requests_signed] = true
192
- end
193
-
194
- it "generates Service Provider Metadata with AuthnRequestsSigned" do
195
- assert_equal "true", spsso_descriptor.attribute("AuthnRequestsSigned").value
196
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
197
- end
198
- end
199
-
200
- describe "and encrypted assertions" do
201
- before do
202
- settings.security[:want_assertions_encrypted] = true
203
- end
204
-
205
- it "generates Service Provider Metadata with X509Certificate for encrypt" do
206
- assert_equal 4, key_descriptors.length
207
- assert_equal "signing", key_descriptors[0].attribute("use").value
208
- assert_equal "encryption", key_descriptors[1].attribute("use").value
209
- assert_equal "signing", key_descriptors[2].attribute("use").value
210
- assert_equal "encryption", key_descriptors[3].attribute("use").value
211
-
212
- assert_equal 4, cert_nodes.length
213
- assert_equal cert_nodes[0].text, cert_nodes[1].text
214
- assert_equal cert_nodes[2].text, cert_nodes[3].text
215
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
216
- end
217
- end
218
-
219
- end
220
-
221
- describe "when attribute service is configured with multiple attribute values" do
222
- let(:attr_svc) { REXML::XPath.first(xml_doc, "//md:AttributeConsumingService") }
223
- let(:req_attr) { REXML::XPath.first(xml_doc, "//md:RequestedAttribute") }
224
-
225
- before do
226
- settings.attribute_consuming_service.configure do
227
- service_name "Test Service"
228
- add_attribute(:name => 'Name', :name_format => 'Name Format', :friendly_name => 'Friendly Name', :attribute_value => ['Attribute Value One', false])
229
- end
230
- end
231
-
232
- it "generates attribute service" do
233
- assert_equal "true", attr_svc.attribute("isDefault").value
234
- assert_equal "1", attr_svc.attribute("index").value
235
- assert_equal REXML::XPath.first(xml_doc, "//md:ServiceName").text.strip, "Test Service"
236
-
237
- assert_equal "Name", req_attr.attribute("Name").value
238
- assert_equal "Name Format", req_attr.attribute("NameFormat").value
239
- assert_equal "Friendly Name", req_attr.attribute("FriendlyName").value
240
-
241
- attribute_values = REXML::XPath.match(xml_doc, "//saml:AttributeValue").map(&:text)
242
- assert_equal "Attribute Value One", attribute_values[0]
243
- assert_equal 'false', attribute_values[1]
244
-
245
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
246
- end
247
- end
248
-
249
- describe "when attribute service is configured" do
250
- let(:attr_svc) { REXML::XPath.first(xml_doc, '//md:AttributeConsumingService') }
251
- let(:req_attr) { REXML::XPath.first(xml_doc, '//md:RequestedAttribute') }
252
-
253
- before do
254
- settings.attribute_consuming_service.configure do
255
- service_name "Test Service"
256
- add_attribute(:name => 'active', :name_format => 'format', :friendly_name => 'Active', :attribute_value => true)
257
- end
258
- end
259
-
260
- it "generates attribute service" do
261
- assert_equal "true", attr_svc.attribute("isDefault").value
262
- assert_equal "1", attr_svc.attribute("index").value
263
- assert_equal REXML::XPath.first(xml_doc, "//md:ServiceName").text.strip, "Test Service"
264
-
265
- assert_equal 'active', req_attr.attribute('Name').value
266
- assert_equal 'format', req_attr.attribute('NameFormat').value
267
- assert_equal 'Active', req_attr.attribute('FriendlyName').value
268
- assert_equal 'true', REXML::XPath.first(xml_doc, '//saml:AttributeValue').text.strip
269
-
270
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
271
- end
272
-
273
- describe "#service_name" do
274
- before do
275
- settings.attribute_consuming_service.service_name("Test2 Service")
276
- end
277
-
278
- it "change service name" do
279
- assert_equal REXML::XPath.first(xml_doc, "//md:ServiceName").text.strip, "Test2 Service"
280
- end
281
- end
282
-
283
- describe "#service_index" do
284
- before do
285
- settings.attribute_consuming_service.service_index(2)
286
- end
287
-
288
- it "change service index" do
289
- assert_equal "2", attr_svc.attribute("index").value
290
- end
291
- end
292
- end
293
-
294
- describe "when the settings indicate to sign (embedded) metadata" do
295
- before do
296
- settings.security[:metadata_signed] = true
297
- settings.certificate = ruby_saml_cert_text
298
- settings.private_key = ruby_saml_key_text
299
- end
300
-
301
- it "creates a signed metadata" do
302
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>]m, xml_text
303
- assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], xml_text
304
- assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], xml_text
305
- signed_metadata = XMLSecurity::SignedDocument.new(xml_text)
306
- assert signed_metadata.validate_document(ruby_saml_cert_fingerprint, false)
307
-
308
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
309
- end
310
-
311
- describe "when digest and signature methods are specified" do
312
- before do
313
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
314
- settings.security[:digest_method] = XMLSecurity::Document::SHA512
315
- end
316
-
317
- it "creates a signed metadata with specified digest and signature methods" do
318
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>]m, xml_text
319
- assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'/>], xml_text
320
- assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha512'/>], xml_text
321
-
322
- signed_metadata_2 = XMLSecurity::SignedDocument.new(xml_text)
323
-
324
- assert signed_metadata_2.validate_document(ruby_saml_cert_fingerprint, false)
325
-
326
- assert validate_xml!(xml_text, "saml-schema-metadata-2.0.xsd")
327
- end
328
- end
329
- end
330
- end
331
- end
data/test/request_test.rb DELETED
@@ -1,323 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
-
3
- require 'onelogin/ruby-saml/authrequest'
4
-
5
- class RequestTest < Minitest::Test
6
-
7
- describe "Authrequest" do
8
- let(:settings) { OneLogin::RubySaml::Settings.new }
9
-
10
- before do
11
- settings.idp_sso_target_url = "http://example.com"
12
- end
13
-
14
- it "create the deflated SAMLRequest URL parameter" do
15
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
16
- assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
17
- payload = CGI.unescape(auth_url.split("=").last)
18
- decoded = Base64.decode64(payload)
19
-
20
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
21
- inflated = zstream.inflate(decoded)
22
- zstream.finish
23
- zstream.close
24
-
25
- assert_match /^<samlp:AuthnRequest/, inflated
26
- end
27
-
28
- it "create the deflated SAMLRequest URL parameter including the Destination" do
29
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
30
- payload = CGI.unescape(auth_url.split("=").last)
31
- decoded = Base64.decode64(payload)
32
-
33
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
34
- inflated = zstream.inflate(decoded)
35
- zstream.finish
36
- zstream.close
37
-
38
- assert_match /<samlp:AuthnRequest[^<]* Destination='http:\/\/example.com'/, inflated
39
- end
40
-
41
- it "create the SAMLRequest URL parameter without deflating" do
42
- settings.compress_request = false
43
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
44
- assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
45
- payload = CGI.unescape(auth_url.split("=").last)
46
- decoded = Base64.decode64(payload)
47
-
48
- assert_match /^<samlp:AuthnRequest/, decoded
49
- end
50
-
51
- it "create the SAMLRequest URL parameter with IsPassive" do
52
- settings.passive = true
53
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
54
- assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
55
- payload = CGI.unescape(auth_url.split("=").last)
56
- decoded = Base64.decode64(payload)
57
-
58
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
59
- inflated = zstream.inflate(decoded)
60
- zstream.finish
61
- zstream.close
62
-
63
- assert_match /<samlp:AuthnRequest[^<]* IsPassive='true'/, inflated
64
- end
65
-
66
- it "create the SAMLRequest URL parameter with ProtocolBinding" do
67
- settings.protocol_binding = 'urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'
68
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
69
- assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
70
- payload = CGI.unescape(auth_url.split("=").last)
71
- decoded = Base64.decode64(payload)
72
-
73
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
74
- inflated = zstream.inflate(decoded)
75
- zstream.finish
76
- zstream.close
77
-
78
- assert_match /<samlp:AuthnRequest[^<]* ProtocolBinding='urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST'/, inflated
79
- end
80
-
81
- it "create the SAMLRequest URL parameter with AttributeConsumingServiceIndex" do
82
- settings.attributes_index = 30
83
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
84
- assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
85
- payload = CGI.unescape(auth_url.split("=").last)
86
- decoded = Base64.decode64(payload)
87
-
88
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
89
- inflated = zstream.inflate(decoded)
90
- zstream.finish
91
- zstream.close
92
- assert_match /<samlp:AuthnRequest[^<]* AttributeConsumingServiceIndex='30'/, inflated
93
- end
94
-
95
- it "create the SAMLRequest URL parameter with ForceAuthn" do
96
- settings.force_authn = true
97
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
98
- assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
99
- payload = CGI.unescape(auth_url.split("=").last)
100
- decoded = Base64.decode64(payload)
101
-
102
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
103
- inflated = zstream.inflate(decoded)
104
- zstream.finish
105
- zstream.close
106
- assert_match /<samlp:AuthnRequest[^<]* ForceAuthn='true'/, inflated
107
- end
108
-
109
- it "create the SAMLRequest URL parameter with NameID Format" do
110
- settings.name_identifier_format = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient"
111
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
112
- assert_match /^http:\/\/example\.com\?SAMLRequest=/, auth_url
113
- payload = CGI.unescape(auth_url.split("=").last)
114
- decoded = Base64.decode64(payload)
115
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
116
- inflated = zstream.inflate(decoded)
117
- zstream.finish
118
- zstream.close
119
-
120
- assert_match /<samlp:NameIDPolicy[^<]* AllowCreate='true'/, inflated
121
- assert_match /<samlp:NameIDPolicy[^<]* Format='urn:oasis:names:tc:SAML:2.0:nameid-format:transient'/, inflated
122
- end
123
-
124
- it "accept extra parameters" do
125
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :hello => "there" })
126
- assert_match /&hello=there$/, auth_url
127
-
128
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :hello => nil })
129
- assert_match /&hello=$/, auth_url
130
- end
131
-
132
- it "RelayState cases" do
133
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :RelayState => nil })
134
- assert !auth_url.include?('RelayState')
135
-
136
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :RelayState => "http://example.com" })
137
- assert auth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
138
-
139
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { 'RelayState' => nil })
140
- assert !auth_url.include?('RelayState')
141
-
142
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { 'RelayState' => "http://example.com" })
143
- assert auth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
144
- end
145
-
146
- describe "when the target url is not set" do
147
- before do
148
- settings.idp_sso_target_url = nil
149
- end
150
-
151
- it "raises an error with a descriptive message" do
152
- err = assert_raises RuntimeError do
153
- OneLogin::RubySaml::Authrequest.new.create(settings)
154
- end
155
- assert_match /idp_sso_target_url is not set/, err.message
156
- end
157
- end
158
-
159
- describe "when the target url doesn't contain a query string" do
160
- it "create the SAMLRequest parameter correctly" do
161
-
162
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
163
- assert_match /^http:\/\/example.com\?SAMLRequest/, auth_url
164
- end
165
- end
166
-
167
- describe "when the target url contains a query string" do
168
- it "create the SAMLRequest parameter correctly" do
169
- settings.idp_sso_target_url = "http://example.com?field=value"
170
-
171
- auth_url = OneLogin::RubySaml::Authrequest.new.create(settings)
172
- assert_match /^http:\/\/example.com\?field=value&SAMLRequest/, auth_url
173
- end
174
- end
175
-
176
- it "create the saml:AuthnContextClassRef element correctly" do
177
- settings.authn_context = 'secure/name/password/uri'
178
- auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
179
- assert_match /<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s
180
- end
181
-
182
- it "create multiple saml:AuthnContextClassRef elements correctly" do
183
- settings.authn_context = ['secure/name/password/uri', 'secure/email/password/uri']
184
- auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
185
- assert_match /<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s
186
- assert_match /<saml:AuthnContextClassRef>secure\/email\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s
187
- end
188
-
189
- it "create the saml:AuthnContextClassRef with comparison exact" do
190
- settings.authn_context = 'secure/name/password/uri'
191
- auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
192
- assert_match /<samlp:RequestedAuthnContext[\S ]+Comparison='exact'/, auth_doc.to_s
193
- assert_match /<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s
194
- end
195
-
196
- it "create the saml:AuthnContextClassRef with comparison minimun" do
197
- settings.authn_context = 'secure/name/password/uri'
198
- settings.authn_context_comparison = 'minimun'
199
- auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
200
- assert_match /<samlp:RequestedAuthnContext[\S ]+Comparison='minimun'/, auth_doc.to_s
201
- assert_match /<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/, auth_doc.to_s
202
- end
203
-
204
- it "create the saml:AuthnContextDeclRef element correctly" do
205
- settings.authn_context_decl_ref = 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
206
- auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
207
- assert_match /<saml:AuthnContextDeclRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport<\/saml:AuthnContextDeclRef>/, auth_doc.to_s
208
- end
209
-
210
- describe "#create_params when the settings indicate to sign (embebed) the request" do
211
- before do
212
- settings.compress_request = false
213
- settings.idp_sso_target_url = "http://example.com?field=value"
214
- settings.security[:authn_requests_signed] = true
215
- settings.security[:embed_sign] = true
216
- settings.certificate = ruby_saml_cert_text
217
- settings.private_key = ruby_saml_key_text
218
- end
219
-
220
- it "create a signed request" do
221
- params = OneLogin::RubySaml::Authrequest.new.create_params(settings)
222
- request_xml = Base64.decode64(params["SAMLRequest"])
223
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
224
- assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], request_xml
225
- end
226
-
227
- it "create a signed request with 256 digest and signature methods" do
228
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
229
- settings.security[:digest_method] = XMLSecurity::Document::SHA512
230
-
231
- params = OneLogin::RubySaml::Authrequest.new.create_params(settings)
232
-
233
- request_xml = Base64.decode64(params["SAMLRequest"])
234
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
235
- assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'/>], request_xml
236
- assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha512'/>], request_xml
237
- end
238
- end
239
-
240
- describe "#create_params when the settings indicate to sign the request" do
241
- let(:cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
242
-
243
- before do
244
- settings.compress_request = false
245
- settings.idp_sso_target_url = "http://example.com?field=value"
246
- settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
247
- settings.security[:authn_requests_signed] = true
248
- settings.security[:embed_sign] = false
249
- settings.certificate = ruby_saml_cert_text
250
- settings.private_key = ruby_saml_key_text
251
- end
252
-
253
- it "create a signature parameter with RSA_SHA1 and validate it" do
254
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
255
-
256
- params = OneLogin::RubySaml::Authrequest.new.create_params(settings, :RelayState => 'http://example.com')
257
- assert params['SAMLRequest']
258
- assert params[:RelayState]
259
- assert params['Signature']
260
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA1
261
-
262
- query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
263
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
264
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
265
-
266
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
267
- assert_equal signature_algorithm, OpenSSL::Digest::SHA1
268
-
269
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
270
- end
271
-
272
- it "create a signature parameter with RSA_SHA256 and validate it" do
273
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
274
-
275
- params = OneLogin::RubySaml::Authrequest.new.create_params(settings, :RelayState => 'http://example.com')
276
- assert params['Signature']
277
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA256
278
-
279
- query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
280
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
281
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
282
-
283
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
284
- assert_equal signature_algorithm, OpenSSL::Digest::SHA256
285
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
286
- end
287
- end
288
-
289
- it "create the saml:AuthnContextClassRef element correctly" do
290
- settings.authn_context = 'secure/name/password/uri'
291
- auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
292
- assert auth_doc.to_s =~ /<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/
293
- end
294
-
295
- it "create the saml:AuthnContextClassRef with comparison exact" do
296
- settings.authn_context = 'secure/name/password/uri'
297
- auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
298
- assert auth_doc.to_s =~ /<samlp:RequestedAuthnContext[\S ]+Comparison='exact'/
299
- assert auth_doc.to_s =~ /<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/
300
- end
301
-
302
- it "create the saml:AuthnContextClassRef with comparison minimun" do
303
- settings.authn_context = 'secure/name/password/uri'
304
- settings.authn_context_comparison = 'minimun'
305
- auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
306
- assert auth_doc.to_s =~ /<samlp:RequestedAuthnContext[\S ]+Comparison='minimun'/
307
- assert auth_doc.to_s =~ /<saml:AuthnContextClassRef>secure\/name\/password\/uri<\/saml:AuthnContextClassRef>/
308
- end
309
-
310
- it "create the saml:AuthnContextDeclRef element correctly" do
311
- settings.authn_context_decl_ref = 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport'
312
- auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
313
- assert auth_doc.to_s =~ /<saml:AuthnContextDeclRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport<\/saml:AuthnContextDeclRef>/
314
- end
315
-
316
- it "create multiple saml:AuthnContextDeclRef elements correctly " do
317
- settings.authn_context_decl_ref = ['name/password/uri', 'example/decl/ref']
318
- auth_doc = OneLogin::RubySaml::Authrequest.new.create_authentication_xml_doc(settings)
319
- assert auth_doc.to_s =~ /<saml:AuthnContextDeclRef>name\/password\/uri<\/saml:AuthnContextDeclRef>/
320
- assert auth_doc.to_s =~ /<saml:AuthnContextDeclRef>example\/decl\/ref<\/saml:AuthnContextDeclRef>/
321
- end
322
- end
323
- end