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,233 +0,0 @@
1
- require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
-
3
- require 'onelogin/ruby-saml/slo_logoutresponse'
4
-
5
- class SloLogoutresponseTest < Minitest::Test
6
-
7
- describe "SloLogoutresponse" do
8
- let(:settings) { OneLogin::RubySaml::Settings.new }
9
- let(:logout_request) { OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document) }
10
-
11
- before do
12
- settings.idp_entity_id = 'https://app.onelogin.com/saml/metadata/SOMEACCOUNT'
13
- settings.idp_slo_target_url = "http://unauth.com/logout"
14
- settings.name_identifier_value = "f00f00"
15
- settings.compress_request = true
16
- settings.certificate = ruby_saml_cert_text
17
- settings.private_key = ruby_saml_key_text
18
- logout_request.settings = settings
19
- end
20
-
21
- it "create the deflated SAMLResponse URL parameter" do
22
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id)
23
- assert_match /^http:\/\/unauth\.com\/logout\?SAMLResponse=/, unauth_url
24
-
25
- inflated = decode_saml_response_payload(unauth_url)
26
- assert_match /^<samlp:LogoutResponse/, inflated
27
- end
28
-
29
- it "support additional params" do
30
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :hello => nil })
31
- assert_match /&hello=$/, unauth_url
32
-
33
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :foo => "bar" })
34
- assert_match /&foo=bar$/, unauth_url
35
-
36
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :RelayState => "http://idp.example.com" })
37
- assert_match /&RelayState=http%3A%2F%2Fidp.example.com$/, unauth_url
38
- end
39
-
40
- it "RelayState cases" do
41
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :RelayState => nil })
42
- assert !unauth_url.include?('RelayState')
43
-
44
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :RelayState => "http://example.com" })
45
- assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
46
-
47
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { 'RelayState' => nil })
48
- assert !unauth_url.include?('RelayState')
49
-
50
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { 'RelayState' => "http://example.com" })
51
- assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
52
- end
53
-
54
- it "set InResponseTo to the ID from the logout request" do
55
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id)
56
-
57
- inflated = decode_saml_response_payload(unauth_url)
58
- assert_match /InResponseTo='_c0348950-935b-0131-1060-782bcb56fcaa'/, inflated
59
- end
60
-
61
- it "set a custom successful logout message on the response" do
62
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, "Custom Logout Message")
63
-
64
- inflated = decode_saml_response_payload(unauth_url)
65
- assert_match /<samlp:StatusMessage>Custom Logout Message<\/samlp:StatusMessage>/, inflated
66
- end
67
-
68
- describe "when the settings indicate to sign (embedded) logout response" do
69
-
70
- before do
71
- settings.compress_response = false
72
- settings.security[:logout_responses_signed] = true
73
- settings.security[:embed_sign] = true
74
- end
75
-
76
- it "doesn't sign through create_xml_document" do
77
- unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
78
- inflated = unauth_res.create_xml_document(settings).to_s
79
-
80
- refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
81
- refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
82
- refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
83
- end
84
-
85
- it "sign unsigned request" do
86
- unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
87
- unauth_res_doc = unauth_res.create_xml_document(settings)
88
- inflated = unauth_res_doc.to_s
89
-
90
- refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
91
- refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
92
- refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
93
-
94
- inflated = unauth_res.sign_document(unauth_res_doc, settings).to_s
95
-
96
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
97
- assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
98
- assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
99
- end
100
-
101
- it "signs through create_logout_response_xml_doc" do
102
- unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
103
- inflated = unauth_res.create_logout_response_xml_doc(settings).to_s
104
-
105
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
106
- assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
107
- assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
108
- end
109
-
110
- it "create a signed logout response" do
111
- logout_request.settings = settings
112
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, logout_request.id, "Custom Logout Message")
113
-
114
- response_xml = Base64.decode64(params["SAMLResponse"])
115
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
116
- assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/, response_xml
117
- assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#sha1'\/>/, response_xml
118
- end
119
-
120
- it "create a signed logout response with 256 digest and signature methods" do
121
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
122
- settings.security[:digest_method] = XMLSecurity::Document::SHA256
123
-
124
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, logout_request.id, "Custom Logout Message")
125
-
126
- response_xml = Base64.decode64(params["SAMLResponse"])
127
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
128
- assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256'\/>/, response_xml
129
- assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha256'\/>/, response_xml
130
- end
131
-
132
- it "create a signed logout response with 512 digest and signature method RSA_SHA384" do
133
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
134
- settings.security[:digest_method] = XMLSecurity::Document::SHA512
135
- logout_request.settings = settings
136
-
137
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, logout_request.id, "Custom Logout Message")
138
-
139
- response_xml = Base64.decode64(params["SAMLResponse"])
140
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
141
- assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha384'\/>/, response_xml
142
- assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha512'\/>/, response_xml
143
- end
144
- end
145
-
146
- describe "#create_params when the settings indicate to sign the logout response" do
147
-
148
- let(:cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
149
-
150
- before do
151
- settings.compress_response = false
152
- settings.security[:logout_responses_signed] = true
153
- settings.security[:embed_sign] = false
154
- end
155
-
156
- it "create a signature parameter with RSA_SHA1 and validate it" do
157
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
158
-
159
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, logout_request.id, "Custom Logout Message", :RelayState => 'http://example.com')
160
- assert params['SAMLResponse']
161
- assert params[:RelayState]
162
- assert params['Signature']
163
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA1
164
-
165
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
166
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
167
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
168
-
169
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
170
- assert_equal signature_algorithm, OpenSSL::Digest::SHA1
171
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
172
- end
173
-
174
- it "create a signature parameter with RSA_SHA256 /SHA256 and validate it" do
175
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
176
-
177
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, logout_request.id, "Custom Logout Message", :RelayState => 'http://example.com')
178
- assert params['SAMLResponse']
179
- assert params[:RelayState]
180
- assert params['Signature']
181
-
182
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA256
183
-
184
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
185
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
186
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
187
-
188
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
189
- assert_equal signature_algorithm, OpenSSL::Digest::SHA256
190
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
191
- end
192
-
193
- it "create a signature parameter with RSA_SHA384 / SHA384 and validate it" do
194
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
195
-
196
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, logout_request.id, "Custom Logout Message", :RelayState => 'http://example.com')
197
- assert params['SAMLResponse']
198
- assert params[:RelayState]
199
- assert params['Signature']
200
-
201
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA384
202
-
203
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
204
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
205
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
206
-
207
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
208
- assert_equal signature_algorithm, OpenSSL::Digest::SHA384
209
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
210
- end
211
-
212
- it "create a signature parameter with RSA_SHA512 / SHA512 and validate it" do
213
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA512
214
-
215
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, logout_request.id, "Custom Logout Message", :RelayState => 'http://example.com')
216
- assert params['SAMLResponse']
217
- assert params[:RelayState]
218
- assert params['Signature']
219
-
220
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA512
221
-
222
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
223
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
224
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
225
-
226
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
227
- assert_equal signature_algorithm, OpenSSL::Digest::SHA512
228
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
229
- end
230
-
231
- end
232
- end
233
- end
data/test/test_helper.rb DELETED
@@ -1,331 +0,0 @@
1
- require 'simplecov'
2
-
3
- SimpleCov.start do
4
- add_filter "test/"
5
- add_filter "vendor/"
6
- add_filter "lib/onelogin/ruby-saml/logging.rb"
7
- end
8
-
9
- require 'stringio'
10
- require 'rubygems'
11
- require 'bundler'
12
- require 'minitest/autorun'
13
- require 'mocha/setup'
14
- require 'timecop'
15
-
16
- Bundler.require :default, :test
17
-
18
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
19
- $LOAD_PATH.unshift(File.dirname(__FILE__))
20
-
21
- require 'onelogin/ruby-saml/logging'
22
-
23
- TEST_LOGGER = Logger.new(StringIO.new)
24
- OneLogin::RubySaml::Logging.logger = TEST_LOGGER
25
-
26
- class Minitest::Test
27
- def fixture(document, base64 = true)
28
- response = Dir.glob(File.join(File.dirname(__FILE__), "responses", "#{document}*")).first
29
- if base64 && response =~ /\.xml$/
30
- Base64.encode64(File.read(response))
31
- else
32
- File.read(response)
33
- end
34
- end
35
-
36
- def read_response(response)
37
- File.read(File.join(File.dirname(__FILE__), "responses", response))
38
- end
39
-
40
- def read_invalid_response(response)
41
- File.read(File.join(File.dirname(__FILE__), "responses", "invalids", response))
42
- end
43
-
44
- def read_logout_request(request)
45
- File.read(File.join(File.dirname(__FILE__), "logout_requests", request))
46
- end
47
-
48
- def read_certificate(certificate)
49
- File.read(File.join(File.dirname(__FILE__), "certificates", certificate))
50
- end
51
-
52
- def response_document_valid_signed
53
- @response_document_valid_signed ||= read_response("valid_response.xml.base64")
54
- end
55
-
56
- def response_document_valid_signed_without_x509certificate
57
- @response_document_valid_signed_without_x509certificate ||= read_response("valid_response_without_x509certificate.xml.base64")
58
- end
59
-
60
- def response_document_without_recipient
61
- @response_document_without_recipient ||= read_response("response_with_undefined_recipient.xml.base64")
62
- end
63
-
64
- def response_document_without_recipient_with_time_updated
65
- doc = Base64.decode64(response_document_without_recipient)
66
- doc.gsub!(/NotBefore=\"(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z\"/, "NotBefore=\"#{(Time.now-300).getutc.strftime("%Y-%m-%dT%XZ")}\"")
67
- doc.gsub!(/NotOnOrAfter=\"(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z\"/, "NotOnOrAfter=\"#{(Time.now+300).getutc.strftime("%Y-%m-%dT%XZ")}\"")
68
- Base64.encode64(doc)
69
- end
70
-
71
- def response_document_without_attributes
72
- @response_document_without_attributes ||= read_response("response_without_attributes.xml.base64")
73
- end
74
-
75
- def response_document_without_reference_uri
76
- @response_document_without_reference_uri ||= read_response("response_without_reference_uri.xml.base64")
77
- end
78
-
79
- def response_document_with_signed_assertion
80
- @response_document_with_signed_assertion ||= read_response("response_with_signed_assertion.xml.base64")
81
- end
82
-
83
- def response_document_with_signed_assertion_2
84
- @response_document_with_signed_assertion_2 ||= read_response("response_with_signed_assertion_2.xml.base64")
85
- end
86
-
87
- def response_document_with_ds_namespace_at_the_root
88
- @response_document_with_ds_namespace_at_the_root ||= read_response("response_with_ds_namespace_at_the_root.xml.base64")
89
- end
90
-
91
- def response_document_unsigned
92
- @response_document_unsigned ||= read_response("response_unsigned_xml_base64")
93
- end
94
-
95
- def response_document_with_saml2_namespace
96
- @response_document_with_saml2_namespace ||= read_response("response_with_saml2_namespace.xml.base64")
97
- end
98
-
99
- def ampersands_document
100
- @ampersands_response ||= read_response("response_with_ampersands.xml.base64")
101
- end
102
-
103
- def response_document_no_cert_and_encrypted_attrs
104
- @response_document_no_cert_and_encrypted_attrs ||= Base64.encode64(read_response("response_no_cert_and_encrypted_attrs.xml"))
105
- end
106
-
107
- def response_document_wrapped
108
- @response_document_wrapped ||= read_response("response_wrapped.xml.base64")
109
- end
110
-
111
- def response_document_assertion_wrapped
112
- @response_document_assertion_wrapped ||= read_response("response_assertion_wrapped.xml.base64")
113
- end
114
-
115
- def response_document_encrypted_nameid
116
- @response_document_encrypted_nameid ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_encrypted_nameid.xml.base64'))
117
- end
118
-
119
- def signed_message_encrypted_unsigned_assertion
120
- @signed_message_encrypted_unsigned_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_unsigned_assertion.xml.base64'))
121
- end
122
-
123
- def signed_message_encrypted_signed_assertion
124
- @signed_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_signed_assertion.xml.base64'))
125
- end
126
-
127
- def unsigned_message_encrypted_signed_assertion
128
- @unsigned_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'unsigned_message_encrypted_signed_assertion.xml.base64'))
129
- end
130
-
131
- def unsigned_message_encrypted_unsigned_assertion
132
- @unsigned_message_encrypted_unsigned_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'unsigned_message_encrypted_unsigned_assertion.xml.base64'))
133
- end
134
-
135
- def response_document_encrypted_attrs
136
- @response_document_encrypted_attrs ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_encrypted_attrs.xml.base64'))
137
- end
138
-
139
- def response_document_double_status_code
140
- @response_document_double_status_code ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_double_status_code.xml.base64'))
141
- end
142
-
143
- def signature_fingerprint_1
144
- @signature_fingerprint1 ||= "C5:19:85:D9:47:F1:BE:57:08:20:25:05:08:46:EB:27:F6:CA:B7:83"
145
- end
146
-
147
- # certificate used on response_with_undefined_recipient
148
- def signature_1
149
- @signature1 ||= read_certificate("certificate1")
150
- end
151
-
152
- # certificate used on response_document_with_signed_assertion_2
153
- def certificate_without_head_foot
154
- @certificate_without_head_foot ||= read_certificate("certificate_without_head_foot")
155
- end
156
-
157
- def idp_metadata_descriptor
158
- @idp_metadata_descriptor ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor.xml'))
159
- end
160
-
161
- def idp_metadata_descriptor2
162
- @idp_metadata_descriptor2 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_2.xml'))
163
- end
164
-
165
- def idp_metadata_descriptor3
166
- @idp_metadata_descriptor3 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_3.xml'))
167
- end
168
-
169
- def idp_metadata_descriptor4
170
- @idp_metadata_descriptor4 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_4.xml'))
171
- end
172
-
173
- def no_idp_metadata_descriptor
174
- @no_idp_metadata_descriptor ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'no_idp_descriptor.xml'))
175
- end
176
-
177
- def idp_metadata_multiple_descriptors
178
- @idp_metadata_multiple_descriptors ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_multiple_descriptors.xml'))
179
- end
180
-
181
- def idp_metadata_multiple_descriptors2
182
- @idp_metadata_multiple_descriptors2 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_multiple_descriptors_2.xml'))
183
- end
184
-
185
- def idp_metadata_multiple_certs
186
- @idp_metadata_multiple_descriptors ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_multi_certs.xml'))
187
- end
188
-
189
- def idp_metadata_multiple_signing_certs
190
- @idp_metadata_multiple_signing_certs ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_multi_signing_certs.xml'))
191
- end
192
-
193
- def idp_metadata_same_sign_and_encrypt_cert
194
- @idp_metadata_same_sign_and_encrypt_cert ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_same_sign_and_encrypt_cert.xml'))
195
- end
196
-
197
- def idp_metadata_different_sign_and_encrypt_cert
198
- @idp_metadata_different_sign_and_encrypt_cert ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_different_sign_and_encrypt_cert.xml'))
199
- end
200
-
201
- def logout_request_document
202
- unless @logout_request_document
203
- xml = read_logout_request("slo_request.xml")
204
- deflated = Zlib::Deflate.deflate(xml, 9)[2..-5]
205
- @logout_request_document = Base64.encode64(deflated)
206
- end
207
- @logout_request_document
208
- end
209
-
210
- def logout_request_document_with_name_id_format
211
- unless @logout_request_document_with_name_id_format
212
- xml = read_logout_request("slo_request_with_name_id_format.xml")
213
- deflated = Zlib::Deflate.deflate(xml, 9)[2..-5]
214
- @logout_request_document_with_name_id_format = Base64.encode64(deflated)
215
- end
216
- @logout_request_document_with_name_id_format
217
- end
218
-
219
- def logout_request_xml_with_session_index
220
- @logout_request_xml_with_session_index ||= File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'slo_request_with_session_index.xml'))
221
- end
222
-
223
- def invalid_logout_request_document
224
- unless @invalid_logout_request_document
225
- xml = File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'invalid_slo_request.xml'))
226
- deflated = Zlib::Deflate.deflate(xml, 9)[2..-5]
227
- @invalid_logout_request_document = Base64.encode64(deflated)
228
- end
229
- @invalid_logout_request_document
230
- end
231
-
232
- def logout_request_base64
233
- @logout_request_base64 ||= File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'slo_request.xml.base64'))
234
- end
235
-
236
- def logout_request_deflated_base64
237
- @logout_request_deflated_base64 ||= File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'slo_request_deflated.xml.base64'))
238
- end
239
-
240
- def ruby_saml_cert
241
- @ruby_saml_cert ||= OpenSSL::X509::Certificate.new(ruby_saml_cert_text)
242
- end
243
-
244
- def ruby_saml_cert2
245
- @ruby_saml_cert2 ||= OpenSSL::X509::Certificate.new(ruby_saml_cert_text2)
246
- end
247
-
248
- def ruby_saml_cert_fingerprint
249
- @ruby_saml_cert_fingerprint ||= Digest::SHA1.hexdigest(ruby_saml_cert.to_der).scan(/../).join(":")
250
- end
251
-
252
- def ruby_saml_cert_text
253
- read_certificate("ruby-saml.crt")
254
- end
255
-
256
- def ruby_saml_cert_text2
257
- read_certificate("ruby-saml-2.crt")
258
- end
259
-
260
- def ruby_saml_key
261
- @ruby_saml_key ||= OpenSSL::PKey::RSA.new(ruby_saml_key_text)
262
- end
263
-
264
- def ruby_saml_key_text
265
- read_certificate("ruby-saml.key")
266
- end
267
-
268
- #
269
- # logoutresponse fixtures
270
- #
271
- def random_id
272
- "_#{OneLogin::RubySaml::Utils.uuid}"
273
- end
274
-
275
- #
276
- # decodes a base64 encoded SAML response for use in SloLogoutresponse tests
277
- #
278
- def decode_saml_response_payload(unauth_url)
279
- payload = CGI.unescape(unauth_url.split("SAMLResponse=").last)
280
- decoded = Base64.decode64(payload)
281
-
282
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
283
- inflated = zstream.inflate(decoded)
284
- zstream.finish
285
- zstream.close
286
- inflated
287
- end
288
-
289
- #
290
- # decodes a base64 encoded SAML request for use in Logoutrequest tests
291
- #
292
- def decode_saml_request_payload(unauth_url)
293
- payload = CGI.unescape(unauth_url.split("SAMLRequest=").last)
294
- decoded = Base64.decode64(payload)
295
-
296
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
297
- inflated = zstream.inflate(decoded)
298
- zstream.finish
299
- zstream.close
300
- inflated
301
- end
302
-
303
- SCHEMA_DIR = File.expand_path(File.join(__FILE__, '../../lib/schemas'))
304
-
305
- #
306
- # validate an xml document against the given schema
307
- #
308
- def validate_xml!(document, schema)
309
- Dir.chdir(SCHEMA_DIR) do
310
- xsd = if schema.is_a? Nokogiri::XML::Schema
311
- schema
312
- else
313
- Nokogiri::XML::Schema(File.read(schema))
314
- end
315
-
316
- xml = if document.is_a? Nokogiri::XML::Document
317
- document
318
- else
319
- Nokogiri::XML(document) { |c| c.strict }
320
- end
321
-
322
- result = xsd.validate(xml)
323
-
324
- if result.length != 0
325
- raise "Schema validation failed! XSD validation errors: #{result.join(", ")}"
326
- else
327
- true
328
- end
329
- end
330
- end
331
- end