ruby-saml 0.8.18 → 0.9

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +1 -6
  4. data/Gemfile +2 -12
  5. data/README.md +363 -35
  6. data/Rakefile +14 -0
  7. data/changelog.md +22 -9
  8. data/lib/onelogin/ruby-saml/attribute_service.rb +34 -0
  9. data/lib/onelogin/ruby-saml/attributes.rb +26 -64
  10. data/lib/onelogin/ruby-saml/authrequest.rb +47 -93
  11. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +87 -0
  12. data/lib/onelogin/ruby-saml/logoutrequest.rb +36 -100
  13. data/lib/onelogin/ruby-saml/logoutresponse.rb +25 -35
  14. data/lib/onelogin/ruby-saml/metadata.rb +46 -16
  15. data/lib/onelogin/ruby-saml/response.rb +63 -373
  16. data/lib/onelogin/ruby-saml/saml_message.rb +78 -0
  17. data/lib/onelogin/ruby-saml/settings.rb +54 -122
  18. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +25 -71
  19. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +37 -102
  20. data/lib/onelogin/ruby-saml/utils.rb +32 -199
  21. data/lib/onelogin/ruby-saml/version.rb +1 -1
  22. data/lib/ruby-saml.rb +5 -2
  23. data/lib/schemas/{saml20assertion_schema.xsd → saml-schema-assertion-2.0.xsd} +283 -283
  24. data/lib/schemas/saml-schema-authn-context-2.0.xsd +23 -0
  25. data/lib/schemas/saml-schema-authn-context-types-2.0.xsd +821 -0
  26. data/lib/schemas/saml-schema-metadata-2.0.xsd +339 -0
  27. data/lib/schemas/{saml20protocol_schema.xsd → saml-schema-protocol-2.0.xsd} +302 -302
  28. data/lib/schemas/sstc-metadata-attr.xsd +35 -0
  29. data/lib/schemas/sstc-saml-attribute-ext.xsd +25 -0
  30. data/lib/schemas/sstc-saml-metadata-algsupport-v1.0.xsd +41 -0
  31. data/lib/schemas/sstc-saml-metadata-ui-v1.0.xsd +89 -0
  32. data/lib/schemas/{xenc_schema.xsd → xenc-schema.xsd} +1 -11
  33. data/lib/schemas/xml.xsd +287 -0
  34. data/lib/schemas/{xmldsig_schema.xsd → xmldsig-core-schema.xsd} +0 -9
  35. data/lib/xml_security.rb +83 -235
  36. data/ruby-saml.gemspec +1 -0
  37. data/test/idp_metadata_parser_test.rb +54 -0
  38. data/test/logoutrequest_test.rb +68 -155
  39. data/test/logoutresponse_test.rb +43 -32
  40. data/test/metadata_test.rb +87 -0
  41. data/test/request_test.rb +102 -99
  42. data/test/response_test.rb +181 -495
  43. data/test/responses/idp_descriptor.xml +3 -0
  44. data/test/responses/logoutresponse_fixtures.rb +7 -8
  45. data/test/responses/response_no_cert_and_encrypted_attrs.xml +29 -0
  46. data/test/responses/response_with_multiple_attribute_values.xml +1 -1
  47. data/test/responses/slo_request.xml +4 -0
  48. data/test/settings_test.rb +25 -112
  49. data/test/slo_logoutrequest_test.rb +40 -50
  50. data/test/slo_logoutresponse_test.rb +86 -185
  51. data/test/test_helper.rb +27 -102
  52. data/test/xml_security_test.rb +114 -337
  53. metadata +30 -81
  54. data/lib/onelogin/ruby-saml/setting_error.rb +0 -6
  55. data/test/certificates/certificate.der +0 -0
  56. data/test/certificates/formatted_certificate +0 -14
  57. data/test/certificates/formatted_chained_certificate +0 -42
  58. data/test/certificates/formatted_private_key +0 -12
  59. data/test/certificates/formatted_rsa_private_key +0 -12
  60. data/test/certificates/invalid_certificate1 +0 -1
  61. data/test/certificates/invalid_certificate2 +0 -1
  62. data/test/certificates/invalid_certificate3 +0 -12
  63. data/test/certificates/invalid_chained_certificate1 +0 -1
  64. data/test/certificates/invalid_private_key1 +0 -1
  65. data/test/certificates/invalid_private_key2 +0 -1
  66. data/test/certificates/invalid_private_key3 +0 -10
  67. data/test/certificates/invalid_rsa_private_key1 +0 -1
  68. data/test/certificates/invalid_rsa_private_key2 +0 -1
  69. data/test/certificates/invalid_rsa_private_key3 +0 -10
  70. data/test/certificates/ruby-saml-2.crt +0 -15
  71. data/test/requests/logoutrequest_fixtures.rb +0 -47
  72. data/test/responses/encrypted_new_attack.xml.base64 +0 -1
  73. data/test/responses/invalids/invalid_issuer_assertion.xml.base64 +0 -1
  74. data/test/responses/invalids/invalid_issuer_message.xml.base64 +0 -1
  75. data/test/responses/invalids/multiple_signed.xml.base64 +0 -1
  76. data/test/responses/invalids/no_signature.xml.base64 +0 -1
  77. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +0 -51
  78. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +0 -49
  79. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +0 -1
  80. data/test/responses/response_node_text_attack.xml.base64 +0 -1
  81. data/test/responses/response_with_concealed_signed_assertion.xml +0 -51
  82. data/test/responses/response_with_doubled_signed_assertion.xml +0 -49
  83. data/test/responses/response_with_multiple_attribute_statements.xml +0 -72
  84. data/test/responses/response_with_signed_assertion_3.xml +0 -30
  85. data/test/responses/response_with_signed_message_and_assertion.xml +0 -34
  86. data/test/responses/response_with_undefined_recipient.xml.base64 +0 -1
  87. data/test/responses/response_wrapped.xml.base64 +0 -150
  88. data/test/responses/valid_response.xml.base64 +0 -1
  89. data/test/responses/valid_response_without_x509certificate.xml.base64 +0 -1
  90. data/test/utils_test.rb +0 -231
@@ -1,245 +1,146 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
2
 
3
- class SloLogoutresponseTest < Minitest::Test
3
+ class SloLogoutresponseTest < Test::Unit::TestCase
4
4
 
5
- describe "SloLogoutresponse" do
5
+ context "SloLogoutresponse" do
6
+ settings = OneLogin::RubySaml::Settings.new
6
7
 
7
- let(:settings) { OneLogin::RubySaml::Settings.new }
8
-
9
- before do
8
+ should "create the deflated SAMLResponse URL parameter" do
10
9
  settings.idp_slo_target_url = "http://unauth.com/logout"
11
10
  settings.name_identifier_value = "f00f00"
12
11
  settings.compress_request = true
13
- settings.certificate = ruby_saml_cert_text
14
- settings.private_key = ruby_saml_key_text
15
- end
16
12
 
17
- it "create the deflated SAMLResponse URL parameter" do
18
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings)
19
- assert_match /^http:\/\/unauth\.com\/logout\?SAMLResponse=/, unauth_url
13
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
20
14
 
21
- inflated = decode_saml_response_payload(unauth_url)
22
- assert_match /^<samlp:LogoutResponse/, inflated
23
- end
15
+ assert request.is_valid?
24
16
 
25
- it "support additional params" do
26
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :hello => nil })
27
- assert_match /&hello=$/, unauth_url
17
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id)
18
+ assert unauth_url =~ /^http:\/\/unauth\.com\/logout\?SAMLResponse=/
28
19
 
29
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :foo => "bar" })
30
- assert_match /&foo=bar$/, unauth_url
20
+ inflated = decode_saml_response_payload(unauth_url)
31
21
 
32
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :RelayState => "http://idp.example.com" })
33
- assert_match /&RelayState=http%3A%2F%2Fidp.example.com$/, unauth_url
22
+ assert_match /^<samlp:LogoutResponse/, inflated
34
23
  end
35
24
 
36
- it "RelayState cases" do
37
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :RelayState => nil })
38
- assert !unauth_url.include?('RelayState')
25
+ should "support additional params" do
26
+ settings.idp_slo_target_url = "http://unauth.com/logout"
27
+ settings.name_identifier_value = "f00f00"
28
+ settings.compress_request = true
39
29
 
40
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { :RelayState => "http://example.com" })
41
- assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
30
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
42
31
 
43
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { 'RelayState' => nil })
44
- assert !unauth_url.include?('RelayState')
32
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, nil, { :hello => nil })
33
+ assert unauth_url =~ /&hello=$/
45
34
 
46
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, nil, { 'RelayState' => "http://example.com" })
47
- assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
35
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, nil, { :foo => "bar" })
36
+ assert unauth_url =~ /&foo=bar$/
37
+
38
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, nil, { :RelayState => "http://idp.example.com" })
39
+ assert unauth_url =~ /&RelayState=http%3A%2F%2Fidp.example.com$/
48
40
  end
49
41
 
50
- it "set InResponseTo to the ID from the logout request" do
51
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, '_c0348950-935b-0131-1060-782bcb56fcaa')
42
+ should "set InResponseTo to the ID from the logout request" do
43
+ settings.idp_slo_target_url = "http://unauth.com/logout"
44
+ settings.name_identifier_value = "f00f00"
45
+ settings.compress_request = true
46
+
47
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
48
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id)
52
49
 
53
50
  inflated = decode_saml_response_payload(unauth_url)
51
+
54
52
  assert_match /InResponseTo='_c0348950-935b-0131-1060-782bcb56fcaa'/, inflated
55
53
  end
56
54
 
57
- it "set a custom successful logout message on the response" do
58
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, "Custom Logout Message")
59
-
60
- inflated = decode_saml_response_payload(unauth_url)
61
- assert_match /<samlp:StatusMessage>Custom Logout Message<\/samlp:StatusMessage>/, inflated
62
- end
55
+ should "set a custom successful logout message on the response" do
56
+ settings.idp_slo_target_url = "http://unauth.com/logout"
57
+ settings.name_identifier_value = "f00f00"
58
+ settings.compress_request = true
63
59
 
64
- it "set a custom logout message and an status on the response" do
65
- unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, nil, "Custom Logout Message", {}, "urn:oasis:names:tc:SAML:2.0:status:PartialLogout")
60
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
61
+ unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, request.id, "Custom Logout Message")
66
62
 
67
63
  inflated = decode_saml_response_payload(unauth_url)
64
+
68
65
  assert_match /<samlp:StatusMessage>Custom Logout Message<\/samlp:StatusMessage>/, inflated
69
- assert_match /<samlp:StatusCode Value='urn:oasis:names:tc:SAML:2.0:status:PartialLogout/, inflated
70
66
  end
71
67
 
72
- describe "when the settings indicate to sign (embedded) logout response" do
73
-
74
- before do
68
+ context "when the settings indicate to sign (embebed) the logout response" do
69
+ should "create a signed logout response" do
70
+ settings = OneLogin::RubySaml::Settings.new
75
71
  settings.compress_response = false
72
+ settings.idp_slo_target_url = "http://example.com?field=value"
76
73
  settings.security[:logout_responses_signed] = true
77
74
  settings.security[:embed_sign] = true
78
- end
79
-
80
- it "doesn't sign through create_xml_document" do
81
- unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
82
- inflated = unauth_res.create_xml_document(settings).to_s
83
-
84
- refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
85
- refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
86
- refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
87
- end
75
+ settings.certificate = ruby_saml_cert_text
76
+ settings.private_key = ruby_saml_key_text
88
77
 
89
- it "sign unsigned request" do
90
- unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
91
- unauth_res_doc = unauth_res.create_xml_document(settings)
92
- inflated = unauth_res_doc.to_s
93
-
94
- refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
95
- refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
96
- refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
97
-
98
- inflated = unauth_res.sign_document(unauth_res_doc, settings).to_s
99
-
100
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
101
- assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
102
- assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
103
- end
104
-
105
- it "signs through create_logout_response_xml_doc" do
106
- unauth_res = OneLogin::RubySaml::SloLogoutresponse.new
107
- inflated = unauth_res.create_logout_response_xml_doc(settings).to_s
108
-
109
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
110
- assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
111
- assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
112
- end
113
-
114
- it "create a signed logout response" do
115
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message")
78
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
79
+ params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
116
80
 
117
81
  response_xml = Base64.decode64(params["SAMLResponse"])
118
82
  assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
119
- assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/, response_xml
120
- assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#sha1'\/>/, response_xml
83
+ response_xml =~ /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/
84
+ response_xml =~ /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#rsa-sha1'\/>/
121
85
  end
122
86
 
123
- it "create a signed logout response with 256 digest and signature methods" do
124
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
125
- settings.security[:digest_method] = XMLSecurity::Document::SHA256
126
-
127
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message")
128
-
129
- response_xml = Base64.decode64(params["SAMLResponse"])
130
- assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
131
- assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256'\/>/, response_xml
132
- assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha256'\/>/, response_xml
133
- end
134
-
135
- it "create a signed logout response with 512 digest and signature method RSA_SHA384" do
136
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
87
+ should "create a signed logout response with 256 digest and signature methods" do
88
+ settings = OneLogin::RubySaml::Settings.new
89
+ settings.compress_response = false
90
+ settings.idp_slo_target_url = "http://example.com?field=value"
91
+ settings.security[:logout_responses_signed] = true
92
+ settings.security[:embed_sign] = true
93
+ settings.security[:signature_method] = XMLSecurity::Document::SHA256
137
94
  settings.security[:digest_method] = XMLSecurity::Document::SHA512
95
+ settings.certificate = ruby_saml_cert_text
96
+ settings.private_key = ruby_saml_key_text
138
97
 
139
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message")
98
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
99
+ params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
140
100
 
141
101
  response_xml = Base64.decode64(params["SAMLResponse"])
142
102
  assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
143
- assert_match /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha384'\/>/, response_xml
144
- assert_match /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmlenc#sha512'\/>/, response_xml
103
+ response_xml =~ /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256'\/>/
104
+ response_xml =~ /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha512'\/>/
145
105
  end
146
106
  end
147
107
 
148
- describe "#create_params when the settings indicate to sign the logout response" do
149
-
150
- let(:cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
151
-
152
- before do
108
+ context "when the settings indicate to sign the logout response" do
109
+ should "create a signature parameter" do
110
+ settings = OneLogin::RubySaml::Settings.new
153
111
  settings.compress_response = false
112
+ settings.idp_slo_target_url = "http://example.com?field=value"
113
+ settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
154
114
  settings.security[:logout_responses_signed] = true
155
115
  settings.security[:embed_sign] = false
156
- end
157
-
158
- it "create a signature parameter with RSA_SHA1 and validate it" do
159
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
116
+ settings.security[:signature_method] = XMLSecurity::Document::SHA1
117
+ settings.certificate = ruby_saml_cert_text
118
+ settings.private_key = ruby_saml_key_text
160
119
 
161
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
162
- assert params['SAMLResponse']
163
- assert params[:RelayState]
120
+ request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
121
+ params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
164
122
  assert params['Signature']
165
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA1
166
-
167
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
168
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
169
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
170
-
171
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
172
- assert_equal signature_algorithm, OpenSSL::Digest::SHA1
173
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
174
- end
123
+ assert params['SigAlg'] == XMLSecurity::Document::SHA1
175
124
 
176
- it "create a signature parameter with RSA_SHA256 /SHA256 and validate it" do
177
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
178
-
179
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
180
- assert params['SAMLResponse']
181
- assert params[:RelayState]
125
+ # signature_method only affects the embedeed signature
126
+ settings.security[:signature_method] = XMLSecurity::Document::SHA256
127
+ params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, request.id, "Custom Logout Message")
182
128
  assert params['Signature']
183
-
184
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA256
185
-
186
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
187
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
188
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
189
-
190
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
191
- assert_equal signature_algorithm, OpenSSL::Digest::SHA256
192
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
129
+ assert params['SigAlg'] == XMLSecurity::Document::SHA1
193
130
  end
131
+ end
194
132
 
195
- it "create a signature parameter with RSA_SHA384 / SHA384 and validate it" do
196
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
197
-
198
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
199
- assert params['SAMLResponse']
200
- assert params[:RelayState]
201
- assert params['Signature']
202
-
203
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA384
204
-
205
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
206
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
207
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
208
-
209
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
210
- assert_equal signature_algorithm, OpenSSL::Digest::SHA384
211
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
212
- end
213
-
214
- it "create a signature parameter with RSA_SHA512 / SHA512 and validate it" do
215
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA512
216
-
217
- params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(settings, nil, "Custom Logout Message", :RelayState => 'http://example.com')
218
- assert params['SAMLResponse']
219
- assert params[:RelayState]
220
- assert params['Signature']
221
-
222
- assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA512
133
+ end
223
134
 
224
- query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
225
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
226
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
135
+ def decode_saml_response_payload(unauth_url)
136
+ payload = CGI.unescape(unauth_url.split("SAMLResponse=").last)
137
+ decoded = Base64.decode64(payload)
227
138
 
228
- signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
229
- assert_equal signature_algorithm, OpenSSL::Digest::SHA512
230
- assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
231
- end
232
- end
233
-
234
- describe "#manipulate response_id" do
235
- it "be able to modify the response id" do
236
- logoutresponse = OneLogin::RubySaml::SloLogoutresponse.new
237
- response_id = logoutresponse.response_id
238
- assert_equal response_id, logoutresponse.uuid
239
- logoutresponse.uuid = "new_uuid"
240
- assert_equal logoutresponse.response_id, logoutresponse.uuid
241
- assert_equal "new_uuid", logoutresponse.response_id
242
- end
243
- end
139
+ zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
140
+ inflated = zstream.inflate(decoded)
141
+ zstream.finish
142
+ zstream.close
143
+ inflated
244
144
  end
145
+
245
146
  end
data/test/test_helper.rb CHANGED
@@ -1,14 +1,9 @@
1
1
  require 'rubygems'
2
- require 'minitest/autorun'
3
- require 'shoulda'
2
+ require 'bundler'
3
+ require 'test/unit'
4
4
  require 'mocha/setup'
5
- require 'timecop'
6
5
 
7
- if RUBY_VERSION < '1.9'
8
- require 'uuid'
9
- else
10
- require 'securerandom'
11
- end
6
+ Bundler.require :default, :test
12
7
 
13
8
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
14
9
  $LOAD_PATH.unshift(File.dirname(__FILE__))
@@ -16,7 +11,7 @@ require 'ruby-saml'
16
11
 
17
12
  ENV["ruby-saml/testing"] = "1"
18
13
 
19
- class Minitest::Test
14
+ class Test::Unit::TestCase
20
15
  def fixture(document, base64 = true)
21
16
  response = Dir.glob(File.join(File.dirname(__FILE__), "responses", "#{document}*")).first
22
17
  if base64 && response =~ /\.xml$/
@@ -26,48 +21,32 @@ class Minitest::Test
26
21
  end
27
22
  end
28
23
 
29
- def random_id
30
- RUBY_VERSION < '1.9' ? "_#{UUID.new.generate}" : "_#{SecureRandom.uuid}"
31
- end
32
-
33
- def read_invalid_response(response)
34
- File.read(File.join(File.dirname(__FILE__), "responses", "invalids", response))
35
- end
36
-
37
- def read_response(response)
38
- File.read(File.join(File.dirname(__FILE__), "responses", response))
39
- end
40
-
41
- def read_certificate(certificate)
42
- File.read(File.join(File.dirname(__FILE__), "certificates", certificate))
43
- end
44
-
45
24
  def response_document
46
- @response_document ||= read_response('response1.xml.base64')
25
+ @response_document ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response1.xml.base64'))
47
26
  end
48
27
 
49
28
  def response_document_2
50
- @response_document2 ||= read_response('response2.xml.base64')
29
+ @response_document2 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response2.xml.base64'))
51
30
  end
52
31
 
53
32
  def response_document_3
54
- @response_document3 ||= read_response('response3.xml.base64')
33
+ @response_document3 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response3.xml.base64'))
55
34
  end
56
35
 
57
36
  def response_document_4
58
- @response_document4 ||= read_response('response4.xml.base64')
37
+ @response_document4 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response4.xml.base64'))
59
38
  end
60
39
 
61
40
  def response_document_5
62
- @response_document5 ||= read_response('response5.xml.base64')
41
+ @response_document5 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response5.xml.base64'))
63
42
  end
64
43
 
65
44
  def r1_response_document_6
66
- @response_document6 ||= read_response('r1_response6.xml.base64')
45
+ @response_document6 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'r1_response6.xml.base64'))
67
46
  end
68
47
 
69
48
  def ampersands_response
70
- @ampersands_resposne ||= read_response('response_with_ampersands.xml.base64')
49
+ @ampersands_response ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_with_ampersands.xml.base64'))
71
50
  end
72
51
 
73
52
  def response_document_6
@@ -77,20 +56,8 @@ class Minitest::Test
77
56
  Base64.encode64(doc)
78
57
  end
79
58
 
80
- def response_document_wrapped
81
- @response_document_wrapped ||= read_response("response_wrapped.xml.base64")
82
- end
83
-
84
- def response_document_valid_signed
85
- response_document_valid_signed ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'valid_response.xml.base64'))
86
- end
87
-
88
- def response_document_valid_signed_without_x509certificate
89
- @response_document_valid_signed_without_x509certificate ||= read_response("valid_response_without_x509certificate.xml.base64")
90
- end
91
-
92
- def response_document_without_recipient
93
- @response_document_without_recipient ||= read_response("response_with_undefined_recipient.xml.base64")
59
+ def response_document_7
60
+ @response_document7 ||= Base64.encode64(File.read(File.join(File.dirname(__FILE__), 'responses', 'response_no_cert_and_encrypted_attrs.xml')))
94
61
  end
95
62
 
96
63
  def wrapped_response_2
@@ -101,87 +68,45 @@ class Minitest::Test
101
68
  @signature_fingerprint1 ||= "C5:19:85:D9:47:F1:BE:57:08:20:25:05:08:46:EB:27:F6:CA:B7:83"
102
69
  end
103
70
 
104
- def signature_fingerprint_valid_res
105
- @signature_fingerprint1 ||= "4b68c453c7d994aad9025c99d5efcf566287fe8d"
106
- end
107
-
108
71
  def signature_1
109
- @signature1 ||= read_certificate('certificate1')
72
+ @signature1 ||= File.read(File.join(File.dirname(__FILE__), 'certificates', 'certificate1'))
110
73
  end
111
74
 
112
75
  def r1_signature_2
113
- @signature2 ||= read_certificate('r1_certificate2_base64')
76
+ @signature2 ||= File.read(File.join(File.dirname(__FILE__), 'certificates', 'r1_certificate2_base64'))
114
77
  end
115
78
 
116
- def valid_cert
117
- @signature_valid_cert ||= read_certificate('ruby-saml.crt')
79
+ def idp_metadata
80
+ @idp_metadata ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'idp_descriptor.xml'))
118
81
  end
119
82
 
120
- def valid_key
121
- @signature_valid_cert ||= read_certificate('ruby-saml.key')
122
- end
123
-
124
- def response_with_multiple_attribute_statements
125
- @response_with_multiple_attribute_statements = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_statements))
126
- end
127
-
128
- def response_multiple_attr_values
129
- @response_multiple_attr_values = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values))
83
+ def logout_request_document
84
+ unless @logout_request_document
85
+ xml = File.read(File.join(File.dirname(__FILE__), 'responses', 'slo_request.xml'))
86
+ deflated = Zlib::Deflate.deflate(xml, 9)[2..-5]
87
+ @logout_request_document = Base64.encode64(deflated)
88
+ end
89
+ @logout_request_document
130
90
  end
131
91
 
132
92
  def ruby_saml_cert
133
93
  @ruby_saml_cert ||= OpenSSL::X509::Certificate.new(ruby_saml_cert_text)
134
94
  end
135
95
 
136
- def ruby_saml_cert2
137
- @ruby_saml_cert2 ||= OpenSSL::X509::Certificate.new(ruby_saml_cert_text2)
138
- end
139
-
140
96
  def ruby_saml_cert_fingerprint
141
97
  @ruby_saml_cert_fingerprint ||= Digest::SHA1.hexdigest(ruby_saml_cert.to_der).scan(/../).join(":")
142
98
  end
143
99
 
144
100
  def ruby_saml_cert_text
145
- read_certificate("ruby-saml.crt")
146
- end
147
-
148
- def ruby_saml_cert_text2
149
- read_certificate("ruby-saml-2.crt")
150
- end
151
-
152
- def ruby_saml_key_text
153
- read_certificate("ruby-saml.key")
101
+ File.read(File.join(File.dirname(__FILE__), 'certificates', 'ruby-saml.crt'))
154
102
  end
155
103
 
156
104
  def ruby_saml_key
157
105
  @ruby_saml_key ||= OpenSSL::PKey::RSA.new(ruby_saml_key_text)
158
106
  end
159
107
 
160
- def read_certificate(certificate)
161
- File.read(File.join(File.dirname(__FILE__), "certificates", certificate))
162
- end
163
-
164
- def decode_saml_request_payload(unauth_url)
165
- payload = CGI.unescape(unauth_url.split("SAMLRequest=").last)
166
- decoded = Base64.decode64(payload)
167
-
168
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
169
- inflated = zstream.inflate(decoded)
170
- zstream.finish
171
- zstream.close
172
- inflated
108
+ def ruby_saml_key_text
109
+ File.read(File.join(File.dirname(__FILE__), 'certificates', 'ruby-saml.key'))
173
110
  end
174
111
 
175
- # decodes a base64 encoded SAML response for use in SloLogoutresponse tests
176
- #
177
- def decode_saml_response_payload(unauth_url)
178
- payload = CGI.unescape(unauth_url.split("SAMLResponse=").last)
179
- decoded = Base64.decode64(payload)
180
-
181
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
182
- inflated = zstream.inflate(decoded)
183
- zstream.finish
184
- zstream.close
185
- inflated
186
- end
187
112
  end