ruby-saml 1.11.0 → 1.12.0

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 (158) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +14 -12
  3. data/README.md +67 -19
  4. data/changelog.md +23 -0
  5. data/lib/onelogin/ruby-saml/attributes.rb +24 -1
  6. data/lib/onelogin/ruby-saml/authrequest.rb +9 -4
  7. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +62 -24
  8. data/lib/onelogin/ruby-saml/logoutrequest.rb +7 -1
  9. data/lib/onelogin/ruby-saml/logoutresponse.rb +4 -0
  10. data/lib/onelogin/ruby-saml/metadata.rb +9 -1
  11. data/lib/onelogin/ruby-saml/response.rb +37 -15
  12. data/lib/onelogin/ruby-saml/saml_message.rb +6 -0
  13. data/lib/onelogin/ruby-saml/setting_error.rb +6 -0
  14. data/lib/onelogin/ruby-saml/settings.rb +34 -2
  15. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +4 -0
  16. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +27 -14
  17. data/lib/onelogin/ruby-saml/utils.rb +56 -0
  18. data/lib/onelogin/ruby-saml/version.rb +1 -1
  19. data/lib/xml_security.rb +34 -6
  20. data/ruby-saml.gemspec +8 -4
  21. metadata +22 -282
  22. data/test/certificates/certificate.der +0 -0
  23. data/test/certificates/certificate1 +0 -12
  24. data/test/certificates/certificate_without_head_foot +0 -1
  25. data/test/certificates/formatted_certificate +0 -14
  26. data/test/certificates/formatted_chained_certificate +0 -42
  27. data/test/certificates/formatted_private_key +0 -12
  28. data/test/certificates/formatted_rsa_private_key +0 -12
  29. data/test/certificates/invalid_certificate1 +0 -1
  30. data/test/certificates/invalid_certificate2 +0 -1
  31. data/test/certificates/invalid_certificate3 +0 -12
  32. data/test/certificates/invalid_chained_certificate1 +0 -1
  33. data/test/certificates/invalid_private_key1 +0 -1
  34. data/test/certificates/invalid_private_key2 +0 -1
  35. data/test/certificates/invalid_private_key3 +0 -10
  36. data/test/certificates/invalid_rsa_private_key1 +0 -1
  37. data/test/certificates/invalid_rsa_private_key2 +0 -1
  38. data/test/certificates/invalid_rsa_private_key3 +0 -10
  39. data/test/certificates/ruby-saml-2.crt +0 -15
  40. data/test/certificates/ruby-saml.crt +0 -14
  41. data/test/certificates/ruby-saml.key +0 -15
  42. data/test/idp_metadata_parser_test.rb +0 -594
  43. data/test/logging_test.rb +0 -62
  44. data/test/logout_requests/invalid_slo_request.xml +0 -6
  45. data/test/logout_requests/slo_request.xml +0 -4
  46. data/test/logout_requests/slo_request.xml.base64 +0 -1
  47. data/test/logout_requests/slo_request_deflated.xml.base64 +0 -1
  48. data/test/logout_requests/slo_request_with_name_id_format.xml +0 -4
  49. data/test/logout_requests/slo_request_with_session_index.xml +0 -5
  50. data/test/logout_responses/logoutresponse_fixtures.rb +0 -86
  51. data/test/logoutrequest_test.rb +0 -260
  52. data/test/logoutresponse_test.rb +0 -427
  53. data/test/metadata/idp_descriptor.xml +0 -26
  54. data/test/metadata/idp_descriptor_2.xml +0 -56
  55. data/test/metadata/idp_descriptor_3.xml +0 -14
  56. data/test/metadata/idp_descriptor_4.xml +0 -72
  57. data/test/metadata/idp_metadata_different_sign_and_encrypt_cert.xml +0 -72
  58. data/test/metadata/idp_metadata_multi_certs.xml +0 -75
  59. data/test/metadata/idp_metadata_multi_signing_certs.xml +0 -52
  60. data/test/metadata/idp_metadata_same_sign_and_encrypt_cert.xml +0 -71
  61. data/test/metadata/idp_multiple_descriptors.xml +0 -59
  62. data/test/metadata/idp_multiple_descriptors_2.xml +0 -59
  63. data/test/metadata/no_idp_descriptor.xml +0 -21
  64. data/test/metadata_test.rb +0 -331
  65. data/test/request_test.rb +0 -340
  66. data/test/response_test.rb +0 -1629
  67. data/test/responses/adfs_response_sha1.xml +0 -46
  68. data/test/responses/adfs_response_sha256.xml +0 -46
  69. data/test/responses/adfs_response_sha384.xml +0 -46
  70. data/test/responses/adfs_response_sha512.xml +0 -46
  71. data/test/responses/adfs_response_xmlns.xml +0 -45
  72. data/test/responses/attackxee.xml +0 -13
  73. data/test/responses/invalids/duplicated_attributes.xml.base64 +0 -1
  74. data/test/responses/invalids/empty_destination.xml.base64 +0 -1
  75. data/test/responses/invalids/empty_nameid.xml.base64 +0 -1
  76. data/test/responses/invalids/encrypted_new_attack.xml.base64 +0 -1
  77. data/test/responses/invalids/invalid_audience.xml.base64 +0 -1
  78. data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
  79. data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
  80. data/test/responses/invalids/invalid_signature_position.xml.base64 +0 -1
  81. data/test/responses/invalids/invalid_subjectconfirmation_inresponse.xml.base64 +0 -1
  82. data/test/responses/invalids/invalid_subjectconfirmation_nb.xml.base64 +0 -1
  83. data/test/responses/invalids/invalid_subjectconfirmation_noa.xml.base64 +0 -1
  84. data/test/responses/invalids/invalid_subjectconfirmation_recipient.xml.base64 +0 -1
  85. data/test/responses/invalids/multiple_assertions.xml.base64 +0 -2
  86. data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
  87. data/test/responses/invalids/no_authnstatement.xml.base64 +0 -1
  88. data/test/responses/invalids/no_conditions.xml.base64 +0 -1
  89. data/test/responses/invalids/no_id.xml.base64 +0 -1
  90. data/test/responses/invalids/no_issuer_assertion.xml.base64 +0 -1
  91. data/test/responses/invalids/no_issuer_response.xml.base64 +0 -1
  92. data/test/responses/invalids/no_nameid.xml.base64 +0 -1
  93. data/test/responses/invalids/no_saml2.xml.base64 +0 -1
  94. data/test/responses/invalids/no_signature.xml.base64 +0 -1
  95. data/test/responses/invalids/no_status.xml.base64 +0 -1
  96. data/test/responses/invalids/no_status_code.xml.base64 +0 -1
  97. data/test/responses/invalids/no_subjectconfirmation_data.xml.base64 +0 -1
  98. data/test/responses/invalids/no_subjectconfirmation_method.xml.base64 +0 -1
  99. data/test/responses/invalids/response_invalid_signed_element.xml.base64 +0 -1
  100. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
  101. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
  102. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
  103. data/test/responses/invalids/status_code_responder.xml.base64 +0 -1
  104. data/test/responses/invalids/status_code_responer_and_msg.xml.base64 +0 -1
  105. data/test/responses/invalids/wrong_spnamequalifier.xml.base64 +0 -1
  106. data/test/responses/no_signature_ns.xml +0 -48
  107. data/test/responses/open_saml_response.xml +0 -56
  108. data/test/responses/response_assertion_wrapped.xml.base64 +0 -93
  109. data/test/responses/response_audience_self_closed_tag.xml.base64 +0 -1
  110. data/test/responses/response_double_status_code.xml.base64 +0 -1
  111. data/test/responses/response_encrypted_attrs.xml.base64 +0 -1
  112. data/test/responses/response_encrypted_nameid.xml.base64 +0 -1
  113. data/test/responses/response_eval.xml +0 -7
  114. data/test/responses/response_no_cert_and_encrypted_attrs.xml +0 -29
  115. data/test/responses/response_node_text_attack.xml.base64 +0 -1
  116. data/test/responses/response_node_text_attack2.xml.base64 +0 -1
  117. data/test/responses/response_node_text_attack3.xml.base64 +0 -1
  118. data/test/responses/response_unsigned_xml_base64 +0 -1
  119. data/test/responses/response_with_ampersands.xml +0 -139
  120. data/test/responses/response_with_ampersands.xml.base64 +0 -93
  121. data/test/responses/response_with_ds_namespace_at_the_root.xml.base64 +0 -1
  122. data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
  123. data/test/responses/response_with_multiple_attribute_values.xml +0 -67
  124. data/test/responses/response_with_retrieval_method.xml +0 -26
  125. data/test/responses/response_with_saml2_namespace.xml.base64 +0 -102
  126. data/test/responses/response_with_signed_assertion.xml.base64 +0 -66
  127. data/test/responses/response_with_signed_assertion_2.xml.base64 +0 -1
  128. data/test/responses/response_with_signed_assertion_3.xml +0 -30
  129. data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
  130. data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
  131. data/test/responses/response_without_attributes.xml.base64 +0 -79
  132. data/test/responses/response_without_reference_uri.xml.base64 +0 -1
  133. data/test/responses/response_wrapped.xml.base64 +0 -150
  134. data/test/responses/signed_message_encrypted_signed_assertion.xml.base64 +0 -1
  135. data/test/responses/signed_message_encrypted_unsigned_assertion.xml.base64 +0 -1
  136. data/test/responses/signed_nameid_in_atts.xml +0 -47
  137. data/test/responses/signed_unqual_nameid_in_atts.xml +0 -47
  138. data/test/responses/simple_saml_php.xml +0 -71
  139. data/test/responses/starfield_response.xml.base64 +0 -1
  140. data/test/responses/test_sign.xml +0 -43
  141. data/test/responses/unsigned_encrypted_adfs.xml +0 -23
  142. data/test/responses/unsigned_message_aes128_encrypted_signed_assertion.xml.base64 +0 -1
  143. data/test/responses/unsigned_message_aes192_encrypted_signed_assertion.xml.base64 +0 -1
  144. data/test/responses/unsigned_message_aes256_encrypted_signed_assertion.xml.base64 +0 -1
  145. data/test/responses/unsigned_message_des192_encrypted_signed_assertion.xml.base64 +0 -1
  146. data/test/responses/unsigned_message_encrypted_assertion_without_saml_namespace.xml.base64 +0 -1
  147. data/test/responses/unsigned_message_encrypted_signed_assertion.xml.base64 +0 -1
  148. data/test/responses/unsigned_message_encrypted_unsigned_assertion.xml.base64 +0 -1
  149. data/test/responses/valid_response.xml.base64 +0 -1
  150. data/test/responses/valid_response_with_formatted_x509certificate.xml.base64 +0 -1
  151. data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
  152. data/test/saml_message_test.rb +0 -56
  153. data/test/settings_test.rb +0 -338
  154. data/test/slo_logoutrequest_test.rb +0 -467
  155. data/test/slo_logoutresponse_test.rb +0 -233
  156. data/test/test_helper.rb +0 -333
  157. data/test/utils_test.rb +0 -259
  158. 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,333 +0,0 @@
1
- require 'simplecov'
2
- require 'coveralls'
3
-
4
- SimpleCov.formatter = Coveralls::SimpleCov::Formatter
5
- SimpleCov.start do
6
- add_filter "test/"
7
- add_filter "vendor/"
8
- add_filter "lib/onelogin/ruby-saml/logging.rb"
9
- end
10
-
11
- require 'stringio'
12
- require 'rubygems'
13
- require 'bundler'
14
- require 'minitest/autorun'
15
- require 'mocha/setup'
16
- require 'timecop'
17
-
18
- Bundler.require :default, :test
19
-
20
- $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
21
- $LOAD_PATH.unshift(File.dirname(__FILE__))
22
-
23
- require 'onelogin/ruby-saml/logging'
24
-
25
- TEST_LOGGER = Logger.new(StringIO.new)
26
- OneLogin::RubySaml::Logging.logger = TEST_LOGGER
27
-
28
- class Minitest::Test
29
- def fixture(document, base64 = true)
30
- response = Dir.glob(File.join(File.dirname(__FILE__), "responses", "#{document}*")).first
31
- if base64 && response =~ /\.xml$/
32
- Base64.encode64(File.read(response))
33
- else
34
- File.read(response)
35
- end
36
- end
37
-
38
- def read_response(response)
39
- File.read(File.join(File.dirname(__FILE__), "responses", response))
40
- end
41
-
42
- def read_invalid_response(response)
43
- File.read(File.join(File.dirname(__FILE__), "responses", "invalids", response))
44
- end
45
-
46
- def read_logout_request(request)
47
- File.read(File.join(File.dirname(__FILE__), "logout_requests", request))
48
- end
49
-
50
- def read_certificate(certificate)
51
- File.read(File.join(File.dirname(__FILE__), "certificates", certificate))
52
- end
53
-
54
- def response_document_valid_signed
55
- @response_document_valid_signed ||= read_response("valid_response.xml.base64")
56
- end
57
-
58
- def response_document_valid_signed_without_x509certificate
59
- @response_document_valid_signed_without_x509certificate ||= read_response("valid_response_without_x509certificate.xml.base64")
60
- end
61
-
62
- def response_document_without_recipient
63
- @response_document_without_recipient ||= read_response("response_with_undefined_recipient.xml.base64")
64
- end
65
-
66
- def response_document_without_recipient_with_time_updated
67
- doc = Base64.decode64(response_document_without_recipient)
68
- 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")}\"")
69
- 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")}\"")
70
- Base64.encode64(doc)
71
- end
72
-
73
- def response_document_without_attributes
74
- @response_document_without_attributes ||= read_response("response_without_attributes.xml.base64")
75
- end
76
-
77
- def response_document_without_reference_uri
78
- @response_document_without_reference_uri ||= read_response("response_without_reference_uri.xml.base64")
79
- end
80
-
81
- def response_document_with_signed_assertion
82
- @response_document_with_signed_assertion ||= read_response("response_with_signed_assertion.xml.base64")
83
- end
84
-
85
- def response_document_with_signed_assertion_2
86
- @response_document_with_signed_assertion_2 ||= read_response("response_with_signed_assertion_2.xml.base64")
87
- end
88
-
89
- def response_document_with_ds_namespace_at_the_root
90
- @response_document_with_ds_namespace_at_the_root ||= read_response("response_with_ds_namespace_at_the_root.xml.base64")
91
- end
92
-
93
- def response_document_unsigned
94
- @response_document_unsigned ||= read_response("response_unsigned_xml_base64")
95
- end
96
-
97
- def response_document_with_saml2_namespace
98
- @response_document_with_saml2_namespace ||= read_response("response_with_saml2_namespace.xml.base64")
99
- end
100
-
101
- def ampersands_document
102
- @ampersands_response ||= read_response("response_with_ampersands.xml.base64")
103
- end
104
-
105
- def response_document_no_cert_and_encrypted_attrs
106
- @response_document_no_cert_and_encrypted_attrs ||= Base64.encode64(read_response("response_no_cert_and_encrypted_attrs.xml"))
107
- end
108
-
109
- def response_document_wrapped
110
- @response_document_wrapped ||= read_response("response_wrapped.xml.base64")
111
- end
112
-
113
- def response_document_assertion_wrapped
114
- @response_document_assertion_wrapped ||= read_response("response_assertion_wrapped.xml.base64")
115
- end
116
-
117
- def response_document_encrypted_nameid
118
- @response_document_encrypted_nameid ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_encrypted_nameid.xml.base64'))
119
- end
120
-
121
- def signed_message_encrypted_unsigned_assertion
122
- @signed_message_encrypted_unsigned_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_unsigned_assertion.xml.base64'))
123
- end
124
-
125
- def signed_message_encrypted_signed_assertion
126
- @signed_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_signed_assertion.xml.base64'))
127
- end
128
-
129
- def unsigned_message_encrypted_signed_assertion
130
- @unsigned_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'unsigned_message_encrypted_signed_assertion.xml.base64'))
131
- end
132
-
133
- def unsigned_message_encrypted_unsigned_assertion
134
- @unsigned_message_encrypted_unsigned_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'unsigned_message_encrypted_unsigned_assertion.xml.base64'))
135
- end
136
-
137
- def response_document_encrypted_attrs
138
- @response_document_encrypted_attrs ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_encrypted_attrs.xml.base64'))
139
- end
140
-
141
- def response_document_double_status_code
142
- @response_document_double_status_code ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_double_status_code.xml.base64'))
143
- end
144
-
145
- def signature_fingerprint_1
146
- @signature_fingerprint1 ||= "C5:19:85:D9:47:F1:BE:57:08:20:25:05:08:46:EB:27:F6:CA:B7:83"
147
- end
148
-
149
- # certificate used on response_with_undefined_recipient
150
- def signature_1
151
- @signature1 ||= read_certificate("certificate1")
152
- end
153
-
154
- # certificate used on response_document_with_signed_assertion_2
155
- def certificate_without_head_foot
156
- @certificate_without_head_foot ||= read_certificate("certificate_without_head_foot")
157
- end
158
-
159
- def idp_metadata_descriptor
160
- @idp_metadata_descriptor ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor.xml'))
161
- end
162
-
163
- def idp_metadata_descriptor2
164
- @idp_metadata_descriptor2 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_2.xml'))
165
- end
166
-
167
- def idp_metadata_descriptor3
168
- @idp_metadata_descriptor3 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_3.xml'))
169
- end
170
-
171
- def idp_metadata_descriptor4
172
- @idp_metadata_descriptor4 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_descriptor_4.xml'))
173
- end
174
-
175
- def no_idp_metadata_descriptor
176
- @no_idp_metadata_descriptor ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'no_idp_descriptor.xml'))
177
- end
178
-
179
- def idp_metadata_multiple_descriptors
180
- @idp_metadata_multiple_descriptors ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_multiple_descriptors.xml'))
181
- end
182
-
183
- def idp_metadata_multiple_descriptors2
184
- @idp_metadata_multiple_descriptors2 ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_multiple_descriptors_2.xml'))
185
- end
186
-
187
- def idp_metadata_multiple_certs
188
- @idp_metadata_multiple_descriptors ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_multi_certs.xml'))
189
- end
190
-
191
- def idp_metadata_multiple_signing_certs
192
- @idp_metadata_multiple_signing_certs ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_multi_signing_certs.xml'))
193
- end
194
-
195
- def idp_metadata_same_sign_and_encrypt_cert
196
- @idp_metadata_same_sign_and_encrypt_cert ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_same_sign_and_encrypt_cert.xml'))
197
- end
198
-
199
- def idp_metadata_different_sign_and_encrypt_cert
200
- @idp_metadata_different_sign_and_encrypt_cert ||= File.read(File.join(File.dirname(__FILE__), 'metadata', 'idp_metadata_different_sign_and_encrypt_cert.xml'))
201
- end
202
-
203
- def logout_request_document
204
- unless @logout_request_document
205
- xml = read_logout_request("slo_request.xml")
206
- deflated = Zlib::Deflate.deflate(xml, 9)[2..-5]
207
- @logout_request_document = Base64.encode64(deflated)
208
- end
209
- @logout_request_document
210
- end
211
-
212
- def logout_request_document_with_name_id_format
213
- unless @logout_request_document_with_name_id_format
214
- xml = read_logout_request("slo_request_with_name_id_format.xml")
215
- deflated = Zlib::Deflate.deflate(xml, 9)[2..-5]
216
- @logout_request_document_with_name_id_format = Base64.encode64(deflated)
217
- end
218
- @logout_request_document_with_name_id_format
219
- end
220
-
221
- def logout_request_xml_with_session_index
222
- @logout_request_xml_with_session_index ||= File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'slo_request_with_session_index.xml'))
223
- end
224
-
225
- def invalid_logout_request_document
226
- unless @invalid_logout_request_document
227
- xml = File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'invalid_slo_request.xml'))
228
- deflated = Zlib::Deflate.deflate(xml, 9)[2..-5]
229
- @invalid_logout_request_document = Base64.encode64(deflated)
230
- end
231
- @invalid_logout_request_document
232
- end
233
-
234
- def logout_request_base64
235
- @logout_request_base64 ||= File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'slo_request.xml.base64'))
236
- end
237
-
238
- def logout_request_deflated_base64
239
- @logout_request_deflated_base64 ||= File.read(File.join(File.dirname(__FILE__), 'logout_requests', 'slo_request_deflated.xml.base64'))
240
- end
241
-
242
- def ruby_saml_cert
243
- @ruby_saml_cert ||= OpenSSL::X509::Certificate.new(ruby_saml_cert_text)
244
- end
245
-
246
- def ruby_saml_cert2
247
- @ruby_saml_cert2 ||= OpenSSL::X509::Certificate.new(ruby_saml_cert_text2)
248
- end
249
-
250
- def ruby_saml_cert_fingerprint
251
- @ruby_saml_cert_fingerprint ||= Digest::SHA1.hexdigest(ruby_saml_cert.to_der).scan(/../).join(":")
252
- end
253
-
254
- def ruby_saml_cert_text
255
- read_certificate("ruby-saml.crt")
256
- end
257
-
258
- def ruby_saml_cert_text2
259
- read_certificate("ruby-saml-2.crt")
260
- end
261
-
262
- def ruby_saml_key
263
- @ruby_saml_key ||= OpenSSL::PKey::RSA.new(ruby_saml_key_text)
264
- end
265
-
266
- def ruby_saml_key_text
267
- read_certificate("ruby-saml.key")
268
- end
269
-
270
- #
271
- # logoutresponse fixtures
272
- #
273
- def random_id
274
- "_#{OneLogin::RubySaml::Utils.uuid}"
275
- end
276
-
277
- #
278
- # decodes a base64 encoded SAML response for use in SloLogoutresponse tests
279
- #
280
- def decode_saml_response_payload(unauth_url)
281
- payload = CGI.unescape(unauth_url.split("SAMLResponse=").last)
282
- decoded = Base64.decode64(payload)
283
-
284
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
285
- inflated = zstream.inflate(decoded)
286
- zstream.finish
287
- zstream.close
288
- inflated
289
- end
290
-
291
- #
292
- # decodes a base64 encoded SAML request for use in Logoutrequest tests
293
- #
294
- def decode_saml_request_payload(unauth_url)
295
- payload = CGI.unescape(unauth_url.split("SAMLRequest=").last)
296
- decoded = Base64.decode64(payload)
297
-
298
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
299
- inflated = zstream.inflate(decoded)
300
- zstream.finish
301
- zstream.close
302
- inflated
303
- end
304
-
305
- SCHEMA_DIR = File.expand_path(File.join(__FILE__, '../../lib/schemas'))
306
-
307
- #
308
- # validate an xml document against the given schema
309
- #
310
- def validate_xml!(document, schema)
311
- Dir.chdir(SCHEMA_DIR) do
312
- xsd = if schema.is_a? Nokogiri::XML::Schema
313
- schema
314
- else
315
- Nokogiri::XML::Schema(File.read(schema))
316
- end
317
-
318
- xml = if document.is_a? Nokogiri::XML::Document
319
- document
320
- else
321
- Nokogiri::XML(document) { |c| c.strict }
322
- end
323
-
324
- result = xsd.validate(xml)
325
-
326
- if result.length != 0
327
- raise "Schema validation failed! XSD validation errors: #{result.join(", ")}"
328
- else
329
- true
330
- end
331
- end
332
- end
333
- end