ruby-saml 0.8.16 → 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 +5 -5
  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 -89
  11. data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +87 -0
  12. data/lib/onelogin/ruby-saml/logoutrequest.rb +34 -93
  13. data/lib/onelogin/ruby-saml/logoutresponse.rb +25 -24
  14. data/lib/onelogin/ruby-saml/metadata.rb +46 -16
  15. data/lib/onelogin/ruby-saml/response.rb +62 -322
  16. data/lib/onelogin/ruby-saml/saml_message.rb +78 -0
  17. data/lib/onelogin/ruby-saml/settings.rb +54 -121
  18. data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +26 -61
  19. data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +27 -84
  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 -144
  39. data/test/logoutresponse_test.rb +43 -25
  40. data/test/metadata_test.rb +87 -0
  41. data/test/request_test.rb +103 -90
  42. data/test/response_test.rb +181 -471
  43. data/test/responses/idp_descriptor.xml +3 -0
  44. data/test/responses/logoutresponse_fixtures.rb +5 -5
  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 +41 -44
  50. data/test/slo_logoutresponse_test.rb +87 -167
  51. data/test/test_helper.rb +27 -102
  52. data/test/xml_security_test.rb +114 -337
  53. metadata +34 -84
  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
@@ -10,6 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.date = Time.now.strftime("%Y-%m-%d")
11
11
  s.description = %q{SAML toolkit for Ruby on Rails}
12
12
  s.email = %q{support@onelogin.com}
13
+ s.license = 'MIT'
13
14
  s.extra_rdoc_files = [
14
15
  "LICENSE",
15
16
  "README.md"
@@ -0,0 +1,54 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
+ require 'net/http'
3
+ require 'net/https'
4
+
5
+ class IdpMetadataParserTest < Test::Unit::TestCase
6
+
7
+ class MockResponse
8
+ attr_accessor :body
9
+ end
10
+
11
+ context "parsing an IdP descriptor file" do
12
+ should "extract settings details from xml" do
13
+ idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
14
+
15
+ settings = idp_metadata_parser.parse(idp_metadata)
16
+
17
+ assert_equal "https://example.hello.com/access/saml/login", settings.idp_sso_target_url
18
+ assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint
19
+ assert_equal "https://example.hello.com/access/saml/logout", settings.idp_slo_target_url
20
+ end
21
+ end
22
+
23
+ context "download and parse IdP descriptor file" do
24
+ setup do
25
+ mock_response = MockResponse.new
26
+ mock_response.body = idp_metadata
27
+ @url = "https://example.com"
28
+ uri = URI(@url)
29
+
30
+ @http = Net::HTTP.new(uri.host, uri.port)
31
+ Net::HTTP.expects(:new).returns(@http)
32
+ @http.expects(:request).returns(mock_response)
33
+ end
34
+
35
+
36
+ should "extract settings from remote xml" do
37
+ idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
38
+ settings = idp_metadata_parser.parse_remote(@url)
39
+
40
+ assert_equal "https://example.hello.com/access/saml/login", settings.idp_sso_target_url
41
+ assert_equal "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72", settings.idp_cert_fingerprint
42
+ assert_equal "https://example.hello.com/access/saml/logout", settings.idp_slo_target_url
43
+ assert_equal OpenSSL::SSL::VERIFY_PEER, @http.verify_mode
44
+ end
45
+
46
+ should "accept self signed certificate if insturcted" do
47
+ idp_metadata_parser = OneLogin::RubySaml::IdpMetadataParser.new
48
+ settings = idp_metadata_parser.parse_remote(@url, false)
49
+
50
+ assert_equal OpenSSL::SSL::VERIFY_NONE, @http.verify_mode
51
+ end
52
+ end
53
+
54
+ end
@@ -1,16 +1,14 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
2
 
3
- class LogoutRequestTest < Minitest::Test
3
+ class RequestTest < Test::Unit::TestCase
4
4
 
5
- describe "Logoutrequest" do
6
- let(:settings) { OneLogin::RubySaml::Settings.new }
5
+ context "Logoutrequest" do
6
+ settings = OneLogin::RubySaml::Settings.new
7
7
 
8
- before do
8
+ should "create the deflated SAMLRequest URL parameter" do
9
9
  settings.idp_slo_target_url = "http://unauth.com/logout"
10
10
  settings.name_identifier_value = "f00f00"
11
- end
12
11
 
13
- it "create the deflated SAMLRequest URL parameter" do
14
12
  unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
15
13
  assert unauth_url =~ /^http:\/\/unauth\.com\/logout\?SAMLRequest=/
16
14
 
@@ -19,7 +17,8 @@ class LogoutRequestTest < Minitest::Test
19
17
  assert_match /^<samlp:LogoutRequest/, inflated
20
18
  end
21
19
 
22
- it "support additional params" do
20
+ should "support additional params" do
21
+
23
22
  unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :hello => nil })
24
23
  assert unauth_url =~ /&hello=$/
25
24
 
@@ -27,8 +26,9 @@ class LogoutRequestTest < Minitest::Test
27
26
  assert unauth_url =~ /&foo=bar$/
28
27
  end
29
28
 
30
- it "set sessionindex" do
31
- sessionidx = random_id
29
+ should "set sessionindex" do
30
+ settings.idp_slo_target_url = "http://example.com"
31
+ sessionidx = UUID.new.generate
32
32
  settings.sessionindex = sessionidx
33
33
 
34
34
  unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :name_id => "there" })
@@ -38,7 +38,9 @@ class LogoutRequestTest < Minitest::Test
38
38
  assert_match %r(#{sessionidx}</samlp:SessionIndex>), inflated
39
39
  end
40
40
 
41
- it "set name_identifier_value" do
41
+ should "set name_identifier_value" do
42
+ settings = OneLogin::RubySaml::Settings.new
43
+ settings.idp_slo_target_url = "http://example.com"
42
44
  settings.name_identifier_format = "transient"
43
45
  name_identifier_value = "abc123"
44
46
  settings.name_identifier_value = name_identifier_value
@@ -50,25 +52,33 @@ class LogoutRequestTest < Minitest::Test
50
52
  assert_match %r(#{name_identifier_value}</saml:NameID>), inflated
51
53
  end
52
54
 
53
- describe "when the target url doesn't contain a query string" do
54
- it "create the SAMLRequest parameter correctly" do
55
+ context "when the target url doesn't contain a query string" do
56
+ should "create the SAMLRequest parameter correctly" do
57
+ settings = OneLogin::RubySaml::Settings.new
55
58
  settings.idp_slo_target_url = "http://example.com"
59
+ settings.name_identifier_value = "f00f00"
60
+
56
61
  unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
57
62
  assert unauth_url =~ /^http:\/\/example.com\?SAMLRequest/
58
63
  end
59
64
  end
60
65
 
61
- describe "when the target url contains a query string" do
62
- it "create the SAMLRequest parameter correctly" do
66
+ context "when the target url contains a query string" do
67
+ should "create the SAMLRequest parameter correctly" do
68
+ settings = OneLogin::RubySaml::Settings.new
63
69
  settings.idp_slo_target_url = "http://example.com?field=value"
70
+ settings.name_identifier_value = "f00f00"
71
+
64
72
  unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings)
65
73
  assert unauth_url =~ /^http:\/\/example.com\?field=value&SAMLRequest/
66
74
  end
67
75
  end
68
76
 
69
- describe "consumation of logout may need to track the transaction" do
70
- it "have access to the request uuid" do
77
+ context "consumation of logout may need to track the transaction" do
78
+ should "have access to the request uuid" do
79
+ settings = OneLogin::RubySaml::Settings.new
71
80
  settings.idp_slo_target_url = "http://example.com?field=value"
81
+ settings.name_identifier_value = "f00f00"
72
82
 
73
83
  unauth_req = OneLogin::RubySaml::Logoutrequest.new
74
84
  unauth_url = unauth_req.create(settings)
@@ -78,167 +88,81 @@ class LogoutRequestTest < Minitest::Test
78
88
  end
79
89
  end
80
90
 
81
-
82
- describe "when the settings indicate to sign (embedded) logout request" do
83
-
84
- before do
91
+ context "when the settings indicate to sign (embebed) the logout request" do
92
+ should "created a signed logout request" do
93
+ settings = OneLogin::RubySaml::Settings.new
94
+ settings.idp_slo_target_url = "http://example.com?field=value"
95
+ settings.name_identifier_value = "f00f00"
85
96
  # sign the logout request
86
97
  settings.security[:logout_requests_signed] = true
87
98
  settings.security[:embed_sign] = true
88
99
  settings.certificate = ruby_saml_cert_text
89
100
  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
101
 
129
102
  unauth_req = OneLogin::RubySaml::Logoutrequest.new
130
103
  unauth_url = unauth_req.create(settings)
131
104
 
132
105
  inflated = decode_saml_request_payload(unauth_url)
133
106
  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
107
  end
137
108
 
138
- it "create a signed logout request with 256 digest and signature method" do
109
+ should "create a signed logout request with 256 digest and signature methods" do
110
+ settings = OneLogin::RubySaml::Settings.new
139
111
  settings.compress_request = false
140
- settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
141
- settings.security[:digest_method] = XMLSecurity::Document::SHA256
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
112
+ settings.idp_slo_target_url = "http://example.com?field=value"
113
+ settings.name_identifier_value = "f00f00"
114
+ # sign the logout request
115
+ settings.security[:logout_requests_signed] = true
116
+ settings.security[:embed_sign] = true
117
+ settings.security[:signature_method] = XMLSecurity::Document::SHA256
154
118
  settings.security[:digest_method] = XMLSecurity::Document::SHA512
119
+ settings.certificate = ruby_saml_cert_text
120
+ settings.private_key = ruby_saml_key_text
155
121
 
156
122
  params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings)
157
123
  request_xml = Base64.decode64(params["SAMLRequest"])
158
124
 
159
125
  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
126
+ request_xml =~ /<ds:SignatureMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha256'\/>/
127
+ request_xml =~ /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2001\/04\/xmldsig-more#rsa-sha512'\/>/
162
128
  end
163
129
  end
164
130
 
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
131
+ context "when the settings indicate to sign the logout request" do
132
+ should "create a signature parameter" do
133
+ settings = OneLogin::RubySaml::Settings.new
134
+ settings.compress_request = false
135
+ settings.idp_slo_target_url = "http://example.com?field=value"
136
+ settings.name_identifier_value = "f00f00"
171
137
  settings.security[:logout_requests_signed] = true
172
138
  settings.security[:embed_sign] = false
173
- settings.certificate = ruby_saml_cert_text
139
+ settings.security[:signature_method] = XMLSecurity::Document::SHA1
140
+ settings.certificate = ruby_saml_cert_text
174
141
  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
142
 
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')
143
+ params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings)
199
144
  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
145
+ assert params['SigAlg'] == XMLSecurity::Document::SHA1
213
146
 
214
- params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, :RelayState => 'http://example.com')
147
+ # signature_method only affects the embedeed signature
148
+ settings.security[:signature_method] = XMLSecurity::Document::SHA256
149
+ params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings)
215
150
  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)
151
+ assert params['SigAlg'] == XMLSecurity::Document::SHA1
225
152
  end
153
+ end
226
154
 
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
155
+ end
233
156
 
234
- query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
235
- query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
236
- query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
157
+ def decode_saml_request_payload(unauth_url)
158
+ payload = CGI.unescape(unauth_url.split("SAMLRequest=").last)
159
+ decoded = Base64.decode64(payload)
237
160
 
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
161
+ zstream = Zlib::Inflate.new(-Zlib::MAX_WBITS)
162
+ inflated = zstream.inflate(decoded)
163
+ zstream.finish
164
+ zstream.close
165
+ inflated
243
166
  end
167
+
244
168
  end
@@ -1,27 +1,26 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
- require File.expand_path(File.join(File.dirname(__FILE__), "responses/logoutresponse_fixtures"))
2
+ require 'rexml/document'
3
+ require 'responses/logoutresponse_fixtures'
4
+ class RubySamlTest < Test::Unit::TestCase
3
5
 
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
6
+ context "Logoutresponse" do
7
+ context "#new" do
8
+ should "raise an exception when response is initialized with nil" do
10
9
  assert_raises(ArgumentError) { OneLogin::RubySaml::Logoutresponse.new(nil) }
11
10
  end
12
- it "default to empty settings" do
11
+ should "default to empty settings" do
13
12
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new( valid_response)
14
- assert logoutresponse.settings.nil?
13
+ assert_nil logoutresponse.settings
15
14
  end
16
- it "accept constructor-injected settings" do
15
+ should "accept constructor-injected settings" do
17
16
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, settings)
18
- assert !logoutresponse.settings.nil?
17
+ assert_not_nil logoutresponse.settings
19
18
  end
20
- it "accept constructor-injected options" do
19
+ should "accept constructor-injected options" do
21
20
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, nil, { :foo => :bar} )
22
21
  assert !logoutresponse.options.empty?
23
22
  end
24
- it "support base64 encoded responses" do
23
+ should "support base64 encoded responses" do
25
24
  expected_response = valid_response
26
25
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(Base64.encode64(expected_response), settings)
27
26
 
@@ -29,21 +28,21 @@ class LogoutResponseTest < Minitest::Test
29
28
  end
30
29
  end
31
30
 
32
- describe "#validate" do
33
- it "validate the response" do
31
+ context "#validate" do
32
+ should "validate the response" do
34
33
  in_relation_to_request_id = random_id
35
- settings.idp_entity_id = "https://example.com/idp"
34
+
36
35
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response({:uuid => in_relation_to_request_id}), settings)
37
36
 
38
37
  assert logoutresponse.validate
39
38
 
40
- assert_equal settings.idp_entity_id, logoutresponse.issuer
39
+ assert_equal settings.issuer, logoutresponse.issuer
41
40
  assert_equal in_relation_to_request_id, logoutresponse.in_response_to
42
41
 
43
42
  assert logoutresponse.success?
44
43
  end
45
44
 
46
- it "invalidate responses with wrong id when given option :matches_uuid" do
45
+ should "invalidate responses with wrong id when given option :matches_uuid" do
47
46
 
48
47
  expected_request_id = "_some_other_expected_uuid"
49
48
  opts = { :matches_request_id => expected_request_id}
@@ -51,10 +50,10 @@ class LogoutResponseTest < Minitest::Test
51
50
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, settings, opts)
52
51
 
53
52
  assert !logoutresponse.validate
54
- assert expected_request_id != logoutresponse.in_response_to
53
+ assert_not_equal expected_request_id, logoutresponse.in_response_to
55
54
  end
56
55
 
57
- it "invalidate responses with wrong request status" do
56
+ should "invalidate responses with wrong request status" do
58
57
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response, settings)
59
58
 
60
59
  assert !logoutresponse.validate
@@ -62,8 +61,8 @@ class LogoutResponseTest < Minitest::Test
62
61
  end
63
62
  end
64
63
 
65
- describe "#validate!" do
66
- it "validates good responses" do
64
+ context "#validate!" do
65
+ should "validates good responses" do
67
66
  in_relation_to_request_id = random_id
68
67
 
69
68
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response({:uuid => in_relation_to_request_id}), settings)
@@ -71,7 +70,7 @@ class LogoutResponseTest < Minitest::Test
71
70
  logoutresponse.validate!
72
71
  end
73
72
 
74
- it "raises validation error when matching for wrong request id" do
73
+ should "raises validation error when matching for wrong request id" do
75
74
 
76
75
  expected_request_id = "_some_other_expected_id"
77
76
  opts = { :matches_request_id => expected_request_id}
@@ -81,13 +80,26 @@ class LogoutResponseTest < Minitest::Test
81
80
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
82
81
  end
83
82
 
84
- it "raise validation error for wrong request status" do
83
+ should "raise validation error for wrong request status" do
85
84
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response, settings)
86
85
 
87
86
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
88
87
  end
89
88
 
90
- it "raise error for invalid xml" do
89
+ should "raise validation error when in bad state" do
90
+ # no settings
91
+ logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response)
92
+ assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
93
+ end
94
+
95
+ should "raise validation error when in lack of issuer setting" do
96
+ bad_settings = settings
97
+ bad_settings.issuer = nil
98
+ logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response, bad_settings)
99
+ assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
100
+ end
101
+
102
+ should "raise error for invalid xml" do
91
103
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(invalid_xml_response, settings)
92
104
 
93
105
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
@@ -95,4 +107,10 @@ class LogoutResponseTest < Minitest::Test
95
107
  end
96
108
 
97
109
  end
110
+
111
+ # logoutresponse fixtures
112
+ def random_id
113
+ "_#{UUID.new.generate}"
114
+ end
115
+
98
116
  end