ruby-saml 0.8.8 → 0.8.13

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 (45) hide show
  1. checksums.yaml +7 -7
  2. data/Gemfile +11 -1
  3. data/README.md +5 -2
  4. data/Rakefile +0 -14
  5. data/lib/onelogin/ruby-saml/authrequest.rb +86 -20
  6. data/lib/onelogin/ruby-saml/logoutrequest.rb +95 -20
  7. data/lib/onelogin/ruby-saml/logoutresponse.rb +5 -28
  8. data/lib/onelogin/ruby-saml/metadata.rb +5 -5
  9. data/lib/onelogin/ruby-saml/response.rb +187 -4
  10. data/lib/onelogin/ruby-saml/setting_error.rb +6 -0
  11. data/lib/onelogin/ruby-saml/settings.rb +146 -10
  12. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +158 -0
  13. data/lib/onelogin/ruby-saml/utils.rb +169 -0
  14. data/lib/onelogin/ruby-saml/version.rb +1 -1
  15. data/lib/ruby-saml.rb +2 -1
  16. data/lib/xml_security.rb +330 -78
  17. data/test/certificates/ruby-saml-2.crt +15 -0
  18. data/test/certificates/ruby-saml.crt +14 -0
  19. data/test/certificates/ruby-saml.key +15 -0
  20. data/test/logoutrequest_test.rb +177 -44
  21. data/test/logoutresponse_test.rb +25 -29
  22. data/test/request_test.rb +100 -37
  23. data/test/response_test.rb +213 -111
  24. data/test/responses/adfs_response_xmlns.xml +45 -0
  25. data/test/responses/encrypted_new_attack.xml.base64 +1 -0
  26. data/test/responses/invalids/multiple_signed.xml.base64 +1 -0
  27. data/test/responses/invalids/no_signature.xml.base64 +1 -0
  28. data/test/responses/invalids/response_with_concealed_signed_assertion.xml +51 -0
  29. data/test/responses/invalids/response_with_doubled_signed_assertion.xml +49 -0
  30. data/test/responses/invalids/signature_wrapping_attack.xml.base64 +1 -0
  31. data/test/responses/logoutresponse_fixtures.rb +6 -6
  32. data/test/responses/response_with_concealed_signed_assertion.xml +51 -0
  33. data/test/responses/response_with_doubled_signed_assertion.xml +49 -0
  34. data/test/responses/response_with_signed_assertion_3.xml +30 -0
  35. data/test/responses/response_with_signed_message_and_assertion.xml +34 -0
  36. data/test/responses/response_with_undefined_recipient.xml.base64 +1 -0
  37. data/test/responses/response_wrapped.xml.base64 +150 -0
  38. data/test/responses/valid_response.xml.base64 +1 -0
  39. data/test/responses/valid_response_without_x509certificate.xml.base64 +1 -0
  40. data/test/settings_test.rb +7 -7
  41. data/test/slo_logoutresponse_test.rb +226 -0
  42. data/test/test_helper.rb +117 -12
  43. data/test/utils_test.rb +10 -10
  44. data/test/xml_security_test.rb +310 -68
  45. metadata +88 -45
@@ -0,0 +1,15 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIICVDCCAb2gAwIBAgIBADANBgkqhkiG9w0BAQ0FADBHMQswCQYDVQQGEwJ1czEQ
3
+ MA4GA1UECAwHZXhhbXBsZTEQMA4GA1UECgwHZXhhbXBsZTEUMBIGA1UEAwwLZXhh
4
+ bXBsZS5jb20wHhcNMTcwNDA3MDgzMDAzWhcNMjcwNDA1MDgzMDAzWjBHMQswCQYD
5
+ VQQGEwJ1czEQMA4GA1UECAwHZXhhbXBsZTEQMA4GA1UECgwHZXhhbXBsZTEUMBIG
6
+ A1UEAwwLZXhhbXBsZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAKhP
7
+ S4/0azxbQekHHewQGKD7Pivr3CDpsrKxY3xlVanxj427OwzOb5KUVzsDEazumt6s
8
+ ZFY8HfidsjXY4EYA4ZzyL7ciIAR5vlAsIYN9nJ4AwVDnN/RjVwj+TN6BqWPLpVIp
9
+ Hc6Dl005HyE0zJnk1DZDn2tQVrIzbD3FhCp7YeotAgMBAAGjUDBOMB0GA1UdDgQW
10
+ BBRYZx4thASfNvR/E7NsCF2IaZ7wIDAfBgNVHSMEGDAWgBRYZx4thASfNvR/E7Ns
11
+ CF2IaZ7wIDAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBDQUAA4GBACz4aobx9aG3
12
+ kh+rNyrlgM3K6dYfnKG1/YH5sJCAOvg8kDr0fQAQifH8lFVWumKUMoAe0bFTfwWt
13
+ p/VJ8MprrEJth6PFeZdczpuv+fpLcNj2VmNVJqvQYvS4m36OnBFh1QFZW8UrbFIf
14
+ dtm2nuZ+twSKqfKwjLdqcoX0p39h7Uw/
15
+ -----END CERTIFICATE-----
@@ -0,0 +1,14 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIICGzCCAYQCCQCNNcQXom32VDANBgkqhkiG9w0BAQUFADBSMQswCQYDVQQGEwJV
3
+ UzELMAkGA1UECBMCSU4xFTATBgNVBAcTDEluZGlhbmFwb2xpczERMA8GA1UEChMI
4
+ T25lTG9naW4xDDAKBgNVBAsTA0VuZzAeFw0xNDA0MjMxODQxMDFaFw0xNTA0MjMx
5
+ ODQxMDFaMFIxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJJTjEVMBMGA1UEBxMMSW5k
6
+ aWFuYXBvbGlzMREwDwYDVQQKEwhPbmVMb2dpbjEMMAoGA1UECxMDRW5nMIGfMA0G
7
+ CSqGSIb3DQEBAQUAA4GNADCBiQKBgQDo6m+QZvYQ/xL0ElLgupK1QDcYL4f5Pckw
8
+ sNgS9pUvV7fzTqCHk8ThLxTk42MQ2McJsOeUJVP728KhymjFCqxgP4VuwRk9rpAl
9
+ 0+mhy6MPdyjyA6G14jrDWS65ysLchK4t/vwpEDz0SQlEoG1kMzllSm7zZS3XregA
10
+ 7DjNaUYQqwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBALM2vGCiQ/vm+a6v40+VX2zd
11
+ qHA2Q/1vF1ibQzJ54MJCOVWvs+vQXfZFhdm0OPM2IrDU7oqvKPqP6xOAeJK6H0yP
12
+ 7M4YL3fatSvIYmmfyXC9kt3Svz/NyrHzPhUnJ0ye/sUSXxnzQxwcm/9PwAqrQaA3
13
+ QpQkH57ybF/OoryPe+2h
14
+ -----END CERTIFICATE-----
@@ -0,0 +1,15 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIICXAIBAAKBgQDo6m+QZvYQ/xL0ElLgupK1QDcYL4f5PckwsNgS9pUvV7fzTqCH
3
+ k8ThLxTk42MQ2McJsOeUJVP728KhymjFCqxgP4VuwRk9rpAl0+mhy6MPdyjyA6G1
4
+ 4jrDWS65ysLchK4t/vwpEDz0SQlEoG1kMzllSm7zZS3XregA7DjNaUYQqwIDAQAB
5
+ AoGBALGR6bRBit+yV5TUU3MZSrf8WQSLWDLgs/33FQSAEYSib4+DJke2lKbI6jkG
6
+ UoSJgFUXFbaQLtMY2+3VDsMKPBdAge9gIdvbkC4yoKjLGm/FBDOxxZcfLpR+9OPq
7
+ U3qM9D0CNuliBWI7Je+p/zs09HIYucpDXy9E18KA1KNF6rfhAkEA9KoNam6wAKnm
8
+ vMzz31ws3RuIOUeo2rx6aaVY95+P9tTxd6U+pNkwxy1aCGP+InVSwlYNA1aQ4Axi
9
+ /GdMIWMkxwJBAPO1CP7cQNZQmu7yusY+GUObDII5YK9WLaY4RAicn5378crPBFxv
10
+ Ukqf9G6FHo7u88iTCIp+vwa3Hn9Tumg3iP0CQQDgUXWBasCVqzCxU5wY4tMDWjXY
11
+ hpoLCpmVeRML3dDJt004rFm2HKe7Rhpw7PTZNQZOxUSjFeA4e0LaNf838UWLAkB8
12
+ QfbHM3ffjhOg96PhhjINdVWoZCb230LBOHj/xxPfUmFTHcBEfQIBSJMxcrBFAnLL
13
+ 9qPpMXymqOFk3ETz9DTlAj8E0qGbp78aVbTOtuwEwNJII+RPw+Zkc+lKR+yaWkAz
14
+ fIXw527NPHH3+rnBG72wyZr9ud4LAum9jh+5No1LQpk=
15
+ -----END RSA PRIVATE KEY-----
@@ -1,14 +1,16 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
2
 
3
- class RequestTest < Test::Unit::TestCase
3
+ class LogoutRequestTest < Minitest::Test
4
4
 
5
- context "Logoutrequest" do
6
- settings = OneLogin::RubySaml::Settings.new
5
+ describe "Logoutrequest" do
6
+ let(:settings) { OneLogin::RubySaml::Settings.new }
7
7
 
8
- should "create the deflated SAMLRequest URL parameter" do
8
+ before do
9
9
  settings.idp_slo_target_url = "http://unauth.com/logout"
10
10
  settings.name_identifier_value = "f00f00"
11
+ end
11
12
 
13
+ it "create the deflated SAMLRequest URL parameter" do
12
14
  unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
13
15
  assert unauth_url =~ /^http:\/\/unauth\.com\/logout\?SAMLRequest=/
14
16
 
@@ -17,8 +19,7 @@ class RequestTest < Test::Unit::TestCase
17
19
  assert_match /^<samlp:LogoutRequest/, inflated
18
20
  end
19
21
 
20
- should "support additional params" do
21
-
22
+ it "support additional params" do
22
23
  unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :hello => nil })
23
24
  assert unauth_url =~ /&hello=$/
24
25
 
@@ -26,9 +27,8 @@ class RequestTest < Test::Unit::TestCase
26
27
  assert unauth_url =~ /&foo=bar$/
27
28
  end
28
29
 
29
- should "set sessionindex" do
30
- settings.idp_slo_target_url = "http://example.com"
31
- sessionidx = UUID.new.generate
30
+ it "set sessionindex" do
31
+ sessionidx = random_id
32
32
  settings.sessionindex = sessionidx
33
33
 
34
34
  unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :name_id => "there" })
@@ -38,9 +38,7 @@ class RequestTest < Test::Unit::TestCase
38
38
  assert_match %r(#{sessionidx}</samlp:SessionIndex>), inflated
39
39
  end
40
40
 
41
- should "set name_identifier_value" do
42
- settings = OneLogin::RubySaml::Settings.new
43
- settings.idp_slo_target_url = "http://example.com"
41
+ it "set name_identifier_value" do
44
42
  settings.name_identifier_format = "transient"
45
43
  name_identifier_value = "abc123"
46
44
  settings.name_identifier_value = name_identifier_value
@@ -52,41 +50,25 @@ class RequestTest < Test::Unit::TestCase
52
50
  assert_match %r(#{name_identifier_value}</saml:NameID>), inflated
53
51
  end
54
52
 
55
- should "require name_identifier_value" do
56
- settings = OneLogin::RubySaml::Settings.new
57
- settings.idp_slo_target_url = "http://example.com"
58
- settings.name_identifier_format = nil
59
-
60
- assert_raises(OneLogin::RubySaml::ValidationError) { OneLogin::RubySaml::Logoutrequest.new.create(settings) }
61
- end
62
-
63
- context "when the target url doesn't contain a query string" do
64
- should "create the SAMLRequest parameter correctly" do
65
- settings = OneLogin::RubySaml::Settings.new
53
+ describe "when the target url doesn't contain a query string" do
54
+ it "create the SAMLRequest parameter correctly" do
66
55
  settings.idp_slo_target_url = "http://example.com"
67
- settings.name_identifier_value = "f00f00"
68
-
69
56
  unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
70
57
  assert unauth_url =~ /^http:\/\/example.com\?SAMLRequest/
71
58
  end
72
59
  end
73
60
 
74
- context "when the target url contains a query string" do
75
- should "create the SAMLRequest parameter correctly" do
76
- settings = OneLogin::RubySaml::Settings.new
61
+ describe "when the target url contains a query string" do
62
+ it "create the SAMLRequest parameter correctly" do
77
63
  settings.idp_slo_target_url = "http://example.com?field=value"
78
- settings.name_identifier_value = "f00f00"
79
-
80
64
  unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
81
65
  assert unauth_url =~ /^http:\/\/example.com\?field=value&SAMLRequest/
82
66
  end
83
67
  end
84
68
 
85
- context "consumation of logout may need to track the transaction" do
86
- should "have access to the request uuid" do
87
- settings = OneLogin::RubySaml::Settings.new
69
+ describe "consumation of logout may need to track the transaction" do
70
+ it "have access to the request uuid" do
88
71
  settings.idp_slo_target_url = "http://example.com?field=value"
89
- settings.name_identifier_value = "f00f00"
90
72
 
91
73
  unauth_req = OneLogin::RubySaml::Logoutrequest.new
92
74
  unauth_url = unauth_req.create(settings)
@@ -95,17 +77,168 @@ class RequestTest < Test::Unit::TestCase
95
77
  assert_match %r[ID='#{unauth_req.uuid}'], inflated
96
78
  end
97
79
  end
98
- end
99
80
 
100
- def decode_saml_request_payload(unauth_url)
101
- payload = CGI.unescape(unauth_url.split("SAMLRequest=").last)
102
- decoded = Base64.decode64(payload)
103
81
 
104
- zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
105
- inflated = zstream.inflate(decoded)
106
- zstream.finish
107
- zstream.close
108
- inflated
109
- end
82
+ describe "when the settings indicate to sign (embedded) logout request" do
83
+
84
+ before do
85
+ # sign the logout request
86
+ settings.security[:logout_requests_signed] = true
87
+ settings.security[:embed_sign] = true
88
+ settings.certificate = ruby_saml_cert_text
89
+ settings.private_key = ruby_saml_key_text
90
+ end
91
+
92
+ it "doesn't sign through create_xml_document" do
93
+ unauth_req = OneLogin::RubySaml::Logoutrequest.new
94
+ inflated = unauth_req.create_xml_document(settings).to_s
95
+
96
+ refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
97
+ refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
98
+ refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
99
+ end
100
+
101
+ it "sign unsigned request" do
102
+ unauth_req = OneLogin::RubySaml::Logoutrequest.new
103
+ unauth_req_doc = unauth_req.create_xml_document(settings)
104
+ inflated = unauth_req_doc.to_s
105
+
106
+ refute_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
107
+ refute_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
108
+ refute_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
109
+
110
+ inflated = unauth_req.sign_document(unauth_req_doc, settings).to_s
111
+
112
+ assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
113
+ assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
114
+ assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
115
+ end
116
+
117
+ it "signs through create_logout_request_xml_doc" do
118
+ unauth_req = OneLogin::RubySaml::Logoutrequest.new
119
+ inflated = unauth_req.create_logout_request_xml_doc(settings).to_s
120
+
121
+ assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
122
+ assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
123
+ assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
124
+ end
125
+
126
+ it "created a signed logout request" do
127
+ settings.compress_request = true
128
+
129
+ unauth_req = OneLogin::RubySaml::Logoutrequest.new
130
+ unauth_url = unauth_req.create(settings)
131
+
132
+ inflated = decode_saml_request_payload(unauth_url)
133
+ assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], inflated
134
+ assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], inflated
135
+ assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], inflated
136
+ end
137
+
138
+ it "create a signed logout request with 256 digest and signature method" do
139
+ settings.compress_request = false
140
+ settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
141
+ settings.security[:digest_method] = XMLSecurity::Document::SHA256
110
142
 
143
+ params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings)
144
+ request_xml = Base64.decode64(params["SAMLRequest"])
145
+
146
+ assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
147
+ assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'/>], request_xml
148
+ assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha256'/>], request_xml
149
+ end
150
+
151
+ it "create a signed logout request with 512 digest and signature method RSA_SHA384" do
152
+ settings.compress_request = false
153
+ settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
154
+ settings.security[:digest_method] = XMLSecurity::Document::SHA512
155
+
156
+ params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings)
157
+ request_xml = Base64.decode64(params["SAMLRequest"])
158
+
159
+ assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
160
+ assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha384'/>], request_xml
161
+ assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmlenc#sha512'/>], request_xml
162
+ end
163
+ end
164
+
165
+ describe "#create_params when the settings indicate to sign the logout request" do
166
+
167
+ let(:cert) { OpenSSL::X509::Certificate.new(ruby_saml_cert_text) }
168
+
169
+ before do
170
+ # sign the logout request
171
+ settings.security[:logout_requests_signed] = true
172
+ settings.security[:embed_sign] = false
173
+ settings.certificate = ruby_saml_cert_text
174
+ settings.private_key = ruby_saml_key_text
175
+ end
176
+
177
+ it "create a signature parameter with RSA_SHA1 / SHA1 and validate it" do
178
+ settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
179
+
180
+ params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
181
+ assert params['SAMLRequest']
182
+ assert params[:RelayState]
183
+ assert params['Signature']
184
+ assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA1
185
+
186
+ query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
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::SHA1
192
+ assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
193
+ end
194
+
195
+ it "create a signature parameter with RSA_SHA256 / SHA256 and validate it" do
196
+ settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
197
+
198
+ params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
199
+ assert params['Signature']
200
+ assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA256
201
+
202
+ query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
203
+ query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
204
+ query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
205
+
206
+ signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
207
+ assert_equal signature_algorithm, OpenSSL::Digest::SHA256
208
+ assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
209
+ end
210
+
211
+ it "create a signature parameter with RSA_SHA384 / SHA384 and validate it" do
212
+ settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA384
213
+
214
+ params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
215
+ assert params['Signature']
216
+ assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA384
217
+
218
+ query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
219
+ query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
220
+ query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
221
+
222
+ signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
223
+ assert_equal signature_algorithm, OpenSSL::Digest::SHA384
224
+ assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
225
+ end
226
+
227
+ it "create a signature parameter with RSA_SHA512 / SHA512 and validate it" do
228
+ settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA512
229
+
230
+ params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
231
+ assert params['Signature']
232
+ assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA512
233
+
234
+ query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
235
+ query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
236
+ query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
237
+
238
+ signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
239
+ assert_equal signature_algorithm, OpenSSL::Digest::SHA512
240
+ assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
241
+ end
242
+ end
243
+ end
111
244
  end
@@ -1,26 +1,27 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
- require 'rexml/document'
3
- require 'responses/logoutresponse_fixtures'
4
- class RubySamlTest < Test::Unit::TestCase
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "responses/logoutresponse_fixtures"))
5
3
 
6
- context "Logoutresponse" do
7
- context "#new" do
8
- should "raise an exception when response is initialized with nil" do
4
+ class LogoutResponseTest < Minitest::Test
5
+
6
+ describe "Logoutresponse" do
7
+
8
+ describe "#new" do
9
+ it "raise an exception when response is initialized with nil" do
9
10
  assert_raises(ArgumentError) { OneLogin::RubySaml::Logoutresponse.new(nil) }
10
11
  end
11
- should "default to empty settings" do
12
+ it "default to empty settings" do
12
13
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new( valid_response)
13
14
  assert logoutresponse.settings.nil?
14
15
  end
15
- should "accept constructor-injected settings" do
16
+ it "accept constructor-injected settings" do
16
17
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, settings)
17
18
  assert !logoutresponse.settings.nil?
18
19
  end
19
- should "accept constructor-injected options" do
20
+ it "accept constructor-injected options" do
20
21
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, nil, { :foo => :bar} )
21
22
  assert !logoutresponse.options.empty?
22
23
  end
23
- should "support base64 encoded responses" do
24
+ it "support base64 encoded responses" do
24
25
  expected_response = valid_response
25
26
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(Base64.encode64(expected_response), settings)
26
27
 
@@ -28,21 +29,21 @@ class RubySamlTest < Test::Unit::TestCase
28
29
  end
29
30
  end
30
31
 
31
- context "#validate" do
32
- should "validate the response" do
32
+ describe "#validate" do
33
+ it "validate the response" do
33
34
  in_relation_to_request_id = random_id
34
35
 
35
36
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response({:uuid => in_relation_to_request_id}), settings)
36
37
 
37
38
  assert logoutresponse.validate
38
39
 
39
- assert_equal settings.issuer, logoutresponse.issuer
40
+ assert_equal settings.sp_entity_id, logoutresponse.issuer
40
41
  assert_equal in_relation_to_request_id, logoutresponse.in_response_to
41
42
 
42
43
  assert logoutresponse.success?
43
44
  end
44
45
 
45
- should "invalidate responses with wrong id when given option :matches_uuid" do
46
+ it "invalidate responses with wrong id when given option :matches_uuid" do
46
47
 
47
48
  expected_request_id = "_some_other_expected_uuid"
48
49
  opts = { :matches_request_id => expected_request_id}
@@ -50,10 +51,10 @@ class RubySamlTest < Test::Unit::TestCase
50
51
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, settings, opts)
51
52
 
52
53
  assert !logoutresponse.validate
53
- assert_not_equal expected_request_id, logoutresponse.in_response_to
54
+ assert expected_request_id != logoutresponse.in_response_to
54
55
  end
55
56
 
56
- should "invalidate responses with wrong request status" do
57
+ it "invalidate responses with wrong request status" do
57
58
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response, settings)
58
59
 
59
60
  assert !logoutresponse.validate
@@ -61,8 +62,8 @@ class RubySamlTest < Test::Unit::TestCase
61
62
  end
62
63
  end
63
64
 
64
- context "#validate!" do
65
- should "validates good responses" do
65
+ describe "#validate!" do
66
+ it "validates good responses" do
66
67
  in_relation_to_request_id = random_id
67
68
 
68
69
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response({:uuid => in_relation_to_request_id}), settings)
@@ -70,7 +71,7 @@ class RubySamlTest < Test::Unit::TestCase
70
71
  logoutresponse.validate!
71
72
  end
72
73
 
73
- should "raises validation error when matching for wrong request id" do
74
+ it "raises validation error when matching for wrong request id" do
74
75
 
75
76
  expected_request_id = "_some_other_expected_id"
76
77
  opts = { :matches_request_id => expected_request_id}
@@ -80,26 +81,27 @@ class RubySamlTest < Test::Unit::TestCase
80
81
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
81
82
  end
82
83
 
83
- should "raise validation error for wrong request status" do
84
+ it "raise validation error for wrong request status" do
84
85
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response, settings)
85
86
 
86
87
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
87
88
  end
88
89
 
89
- should "raise validation error when in bad state" do
90
+ it "raise validation error when in bad state" do
90
91
  # no settings
91
92
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response)
92
93
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
93
94
  end
94
95
 
95
- should "raise validation error when in lack of issuer setting" do
96
+ it "raise validation error when in lack of sp_entity_id setting" do
96
97
  bad_settings = settings
97
98
  bad_settings.issuer = nil
99
+ bad_settings.sp_entity_id = nil
98
100
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response, bad_settings)
99
101
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
100
102
  end
101
103
 
102
- should "raise error for invalid xml" do
104
+ it "raise error for invalid xml" do
103
105
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(invalid_xml_response, settings)
104
106
 
105
107
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
@@ -107,10 +109,4 @@ class RubySamlTest < Test::Unit::TestCase
107
109
  end
108
110
 
109
111
  end
110
-
111
- # logoutresponse fixtures
112
- def random_id
113
- "_#{UUID.new.generate}"
114
- end
115
-
116
112
  end