ruby-saml 0.9.1 → 0.9.2
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.
- checksums.yaml +4 -4
- data/.travis.yml +10 -0
- data/Gemfile +1 -1
- data/README.md +31 -7
- data/changelog.md +18 -0
- data/gemfiles/nokogiri-1.5.gemfile +5 -0
- data/lib/onelogin/ruby-saml.rb +16 -0
- data/lib/onelogin/ruby-saml/authrequest.rb +10 -5
- data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +20 -1
- data/lib/onelogin/ruby-saml/logoutrequest.rb +9 -5
- data/lib/onelogin/ruby-saml/logoutresponse.rb +2 -0
- data/lib/onelogin/ruby-saml/metadata.rb +16 -6
- data/lib/onelogin/ruby-saml/response.rb +17 -15
- data/lib/onelogin/ruby-saml/saml_message.rb +44 -30
- data/lib/onelogin/ruby-saml/settings.rb +17 -7
- data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +2 -0
- data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +9 -5
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/ruby-saml.rb +1 -16
- data/lib/xml_security.rb +39 -17
- data/ruby-saml.gemspec +5 -6
- data/test/idp_metadata_parser_test.rb +6 -2
- data/test/logoutrequest_test.rb +50 -22
- data/test/logoutresponse_test.rb +2 -1
- data/test/metadata_test.rb +100 -55
- data/test/request_test.rb +49 -24
- data/test/response_test.rb +41 -8
- data/test/responses/test_sign.xml +43 -0
- data/test/settings_test.rb +16 -0
- data/test/slo_logoutrequest_test.rb +2 -0
- data/test/slo_logoutresponse_test.rb +51 -21
- data/test/test_helper.rb +0 -1
- data/test/xml_security_test.rb +41 -4
- metadata +10 -6
data/test/request_test.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
2
|
|
3
|
+
require 'onelogin/ruby-saml/authrequest'
|
4
|
+
|
3
5
|
class RequestTest < Minitest::Test
|
4
6
|
|
5
7
|
describe "Authrequest" do
|
@@ -143,7 +145,7 @@ class RequestTest < Minitest::Test
|
|
143
145
|
end
|
144
146
|
end
|
145
147
|
|
146
|
-
describe "when the settings indicate to sign (embebed) the request" do
|
148
|
+
describe "#create_params when the settings indicate to sign (embebed) the request" do
|
147
149
|
it "create a signed request" do
|
148
150
|
settings = OneLogin::RubySaml::Settings.new
|
149
151
|
settings.compress_request = false
|
@@ -156,8 +158,8 @@ class RequestTest < Minitest::Test
|
|
156
158
|
params = OneLogin::RubySaml::Authrequest.new.create_params(settings)
|
157
159
|
request_xml = Base64.decode64(params["SAMLRequest"])
|
158
160
|
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
|
159
|
-
|
160
|
-
|
161
|
+
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2000/09/xmldsig#rsa-sha1'/>], request_xml
|
162
|
+
assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2000/09/xmldsig#sha1'/>], request_xml
|
161
163
|
end
|
162
164
|
|
163
165
|
it "create a signed request with 256 digest and signature methods" do
|
@@ -166,7 +168,7 @@ class RequestTest < Minitest::Test
|
|
166
168
|
settings.idp_sso_target_url = "http://example.com?field=value"
|
167
169
|
settings.security[:authn_requests_signed] = true
|
168
170
|
settings.security[:embed_sign] = true
|
169
|
-
settings.security[:signature_method] = XMLSecurity::Document::
|
171
|
+
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
|
170
172
|
settings.security[:digest_method] = XMLSecurity::Document::SHA512
|
171
173
|
settings.certificate = ruby_saml_cert_text
|
172
174
|
settings.private_key = ruby_saml_key_text
|
@@ -174,33 +176,56 @@ class RequestTest < Minitest::Test
|
|
174
176
|
params = OneLogin::RubySaml::Authrequest.new.create_params(settings)
|
175
177
|
request_xml = Base64.decode64(params["SAMLRequest"])
|
176
178
|
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], request_xml
|
177
|
-
|
178
|
-
|
179
|
+
assert_match %r[<ds:SignatureMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'/>], request_xml
|
180
|
+
assert_match %r[<ds:DigestMethod Algorithm='http://www.w3.org/2001/04/xmldsig-more#sha512'/>], request_xml
|
179
181
|
end
|
180
182
|
end
|
181
183
|
|
184
|
+
describe "#create_params when the settings indicate to sign the request" do
|
185
|
+
def setup
|
186
|
+
@settings = OneLogin::RubySaml::Settings.new
|
187
|
+
@settings.compress_request = false
|
188
|
+
@settings.idp_sso_target_url = "http://example.com?field=value"
|
189
|
+
@settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
|
190
|
+
@settings.security[:authn_requests_signed] = true
|
191
|
+
@settings.security[:embed_sign] = false
|
192
|
+
@settings.certificate = ruby_saml_cert_text
|
193
|
+
@settings.private_key = ruby_saml_key_text
|
194
|
+
@cert = OpenSSL::X509::Certificate.new(ruby_saml_cert_text)
|
195
|
+
end
|
196
|
+
|
197
|
+
it "create a signature parameter with RSA_SHA1 and validate it" do
|
198
|
+
@settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
182
199
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
settings.compress_request = false
|
187
|
-
settings.idp_sso_target_url = "http://example.com?field=value"
|
188
|
-
settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
|
189
|
-
settings.security[:authn_requests_signed] = true
|
190
|
-
settings.security[:embed_sign] = false
|
191
|
-
settings.security[:signature_method] = XMLSecurity::Document::SHA1
|
192
|
-
settings.certificate = ruby_saml_cert_text
|
193
|
-
settings.private_key = ruby_saml_key_text
|
194
|
-
|
195
|
-
params = OneLogin::RubySaml::Authrequest.new.create_params(settings)
|
200
|
+
params = OneLogin::RubySaml::Authrequest.new.create_params(@settings, :RelayState => 'http://example.com')
|
201
|
+
assert params['SAMLRequest']
|
202
|
+
assert params[:RelayState]
|
196
203
|
assert params['Signature']
|
197
|
-
|
204
|
+
assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA1
|
198
205
|
|
199
|
-
|
200
|
-
|
201
|
-
|
206
|
+
query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
|
207
|
+
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
|
208
|
+
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
|
209
|
+
|
210
|
+
signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
|
211
|
+
assert_equal signature_algorithm, OpenSSL::Digest::SHA1
|
212
|
+
assert @cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
|
213
|
+
end
|
214
|
+
|
215
|
+
it "create a signature parameter with RSA_SHA256 and validate it" do
|
216
|
+
@settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
|
217
|
+
|
218
|
+
params = OneLogin::RubySaml::Authrequest.new.create_params(@settings, :RelayState => 'http://example.com')
|
202
219
|
assert params['Signature']
|
203
|
-
|
220
|
+
assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA256
|
221
|
+
|
222
|
+
query_string = "SAMLRequest=#{CGI.escape(params['SAMLRequest'])}"
|
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::SHA256
|
228
|
+
assert @cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
|
204
229
|
end
|
205
230
|
end
|
206
231
|
|
data/test/response_test.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
2
|
|
3
|
+
require 'onelogin/ruby-saml/response'
|
4
|
+
|
3
5
|
class RubySamlTest < Minitest::Test
|
4
6
|
|
5
7
|
describe "Response" do
|
@@ -119,7 +121,7 @@ class RubySamlTest < Minitest::Test
|
|
119
121
|
settings.idp_cert_fingerprint = signature_fingerprint_1
|
120
122
|
response.settings = settings
|
121
123
|
assert response.is_valid?
|
122
|
-
|
124
|
+
assert_equal response.name_id, "test@onelogin.com"
|
123
125
|
end
|
124
126
|
|
125
127
|
it "support dynamic namespace resolution on signature elements" do
|
@@ -193,15 +195,23 @@ class RubySamlTest < Minitest::Test
|
|
193
195
|
assert response.send(:validate_conditions, true)
|
194
196
|
end
|
195
197
|
|
196
|
-
it "optionally
|
198
|
+
it "optionally allows for clock drift" do
|
197
199
|
# The NotBefore condition in the document is 2011-06-14T18:21:01.516Z
|
198
|
-
|
199
|
-
|
200
|
-
|
200
|
+
Timecop.freeze(Time.parse("2011-06-14T18:21:01Z")) do
|
201
|
+
response = OneLogin::RubySaml::Response.new(
|
202
|
+
response_document_5,
|
203
|
+
:allowed_clock_drift => 0.515
|
204
|
+
)
|
205
|
+
assert !response.send(:validate_conditions, true)
|
206
|
+
end
|
201
207
|
|
202
|
-
|
203
|
-
|
204
|
-
|
208
|
+
Timecop.freeze(Time.parse("2011-06-14T18:21:01Z")) do
|
209
|
+
response = OneLogin::RubySaml::Response.new(
|
210
|
+
response_document_5,
|
211
|
+
:allowed_clock_drift => 0.516
|
212
|
+
)
|
213
|
+
assert response.send(:validate_conditions, true)
|
214
|
+
end
|
205
215
|
end
|
206
216
|
end
|
207
217
|
|
@@ -376,5 +386,28 @@ class RubySamlTest < Minitest::Test
|
|
376
386
|
assert_equal($evalled, nil)
|
377
387
|
end
|
378
388
|
end
|
389
|
+
|
390
|
+
describe '#sign_document' do
|
391
|
+
it 'Sign an unsigned SAML Response XML and initiate the SAML object with it' do
|
392
|
+
xml = Base64.decode64(fixture("test_sign.xml"))
|
393
|
+
|
394
|
+
document = XMLSecurity::Document.new(xml)
|
395
|
+
|
396
|
+
formated_cert = OneLogin::RubySaml::Utils.format_cert(ruby_saml_cert_text)
|
397
|
+
cert = OpenSSL::X509::Certificate.new(formated_cert)
|
398
|
+
|
399
|
+
formated_private_key = OneLogin::RubySaml::Utils.format_private_key(ruby_saml_key_text)
|
400
|
+
private_key = OpenSSL::PKey::RSA.new(formated_private_key)
|
401
|
+
document.sign_document(private_key, cert)
|
402
|
+
|
403
|
+
saml_response = OneLogin::RubySaml::Response.new(document.to_s)
|
404
|
+
settings = OneLogin::RubySaml::Settings.new
|
405
|
+
settings.idp_cert = ruby_saml_cert_text
|
406
|
+
saml_response.settings = settings
|
407
|
+
time = Time.parse("2015-03-18T04:50:24Z")
|
408
|
+
Time.stubs(:now).returns(time)
|
409
|
+
saml_response.validate!
|
410
|
+
end
|
411
|
+
end
|
379
412
|
end
|
380
413
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
<?xml version='1.0' encoding='UTF-8'?>
|
2
|
+
<samlp:Response Destination='http://recipient' ID='R6fa6c6bfb42798aa6d2893740f1e8d0fc361ac23' InResponseTo='_36387b60-af58-0132-6be9-6c4008ad82d2' IssueInstant='2015-03-18T04:50:24Z' Version='2.0' xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion' xmlns:samlp='urn:oasis:names:tc:SAML:2.0:protocol'>
|
3
|
+
<saml:Issuer>https://app.onelogin.com/saml/metadata/433789</saml:Issuer>
|
4
|
+
<samlp:Status>
|
5
|
+
<samlp:StatusCode Value='urn:oasis:names:tc:SAML:2.0:status:Success'/>
|
6
|
+
</samlp:Status>
|
7
|
+
<saml:Assertion ID='pfxcb6907fc-cd01-59eb-a50f-513689085a71' IssueInstant='2015-03-18T04:50:24Z' Version='2.0' xmlns:saml='urn:oasis:names:tc:SAML:2.0:assertion' xmlns:xs='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>
|
8
|
+
<saml:Issuer>https://app.onelogin.com/saml/metadata/433789</saml:Issuer>
|
9
|
+
<saml:Subject>
|
10
|
+
<saml:NameID Format='urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress'>jane.doe@example.com</saml:NameID>
|
11
|
+
<saml:SubjectConfirmation Method='urn:oasis:names:tc:SAML:2.0:cm:bearer'>
|
12
|
+
<saml:SubjectConfirmationData InResponseTo='_36387b60-af58-0132-6be9-6c4008ad82d2' NotOnOrAfter='2015-03-19T17:57:12Z' Recipient='http://recipient'/>
|
13
|
+
</saml:SubjectConfirmation>
|
14
|
+
</saml:Subject>
|
15
|
+
<saml:Conditions NotBefore='2015-03-18T04:47:24Z' NotOnOrAfter='2015-03-19T17:57:12Z'>
|
16
|
+
<saml:AudienceRestriction>
|
17
|
+
<saml:Audience>http://audience</saml:Audience>
|
18
|
+
</saml:AudienceRestriction>
|
19
|
+
</saml:Conditions>
|
20
|
+
<saml:AuthnStatement AuthnInstant='2015-03-18T04:50:23Z' SessionIndex='_f4610090-af35-0132-899e-38ca3a662f1c' SessionNotOnOrAfter='2015-03-19T04:50:24Z'>
|
21
|
+
<saml:AuthnContext>
|
22
|
+
<saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef>
|
23
|
+
</saml:AuthnContext>
|
24
|
+
</saml:AuthnStatement>
|
25
|
+
<saml:AttributeStatement>
|
26
|
+
<saml:Attribute Name='User.email' NameFormat='urn:oasis:names:tc:SAML:2.0:attrname-format:basic'>
|
27
|
+
<saml:AttributeValue xsi:type='xs:string' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>jane.doe@example.com</saml:AttributeValue>
|
28
|
+
</saml:Attribute>
|
29
|
+
<saml:Attribute Name='User.FirstName' NameFormat='urn:oasis:names:tc:SAML:2.0:attrname-format:basic'>
|
30
|
+
<saml:AttributeValue xsi:type='xs:string' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>Jane</saml:AttributeValue>
|
31
|
+
</saml:Attribute>
|
32
|
+
<saml:Attribute Name='User.LastName' NameFormat='urn:oasis:names:tc:SAML:2.0:attrname-format:basic'>
|
33
|
+
<saml:AttributeValue xsi:type='xs:string' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'>Doe</saml:AttributeValue>
|
34
|
+
</saml:Attribute>
|
35
|
+
<saml:Attribute Name='PersonImmutableID' NameFormat='urn:oasis:names:tc:SAML:2.0:attrname-format:basic'>
|
36
|
+
<saml:AttributeValue xsi:type='xs:string' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'/>
|
37
|
+
</saml:Attribute>
|
38
|
+
<saml:Attribute Name='memberOf' NameFormat='urn:oasis:names:tc:SAML:2.0:attrname-format:basic'>
|
39
|
+
<saml:AttributeValue xsi:type='xs:string' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'/>
|
40
|
+
</saml:Attribute>
|
41
|
+
</saml:AttributeStatement>
|
42
|
+
</saml:Assertion>
|
43
|
+
</samlp:Response>
|
data/test/settings_test.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
2
|
|
3
|
+
require 'onelogin/ruby-saml/settings'
|
4
|
+
|
3
5
|
class SettingsTest < Minitest::Test
|
4
6
|
|
5
7
|
describe "Settings" do
|
@@ -61,5 +63,19 @@ class SettingsTest < Minitest::Test
|
|
61
63
|
assert_equal @settings.attribute_consuming_service.name, "Test Service"
|
62
64
|
assert_equal @settings.attribute_consuming_service.attributes, [{:name => "Name", :name_format => "Name Format", :friendly_name => "Friendly Name" }]
|
63
65
|
end
|
66
|
+
|
67
|
+
it "does not modify default security settings" do
|
68
|
+
settings = OneLogin::RubySaml::Settings.new
|
69
|
+
settings.security[:authn_requests_signed] = true
|
70
|
+
settings.security[:embed_sign] = true
|
71
|
+
settings.security[:digest_method] = XMLSecurity::Document::SHA256
|
72
|
+
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
|
73
|
+
|
74
|
+
new_settings = OneLogin::RubySaml::Settings.new
|
75
|
+
assert_equal new_settings.security[:authn_requests_signed], false
|
76
|
+
assert_equal new_settings.security[:embed_sign], false
|
77
|
+
assert_equal new_settings.security[:digest_method], XMLSecurity::Document::SHA1
|
78
|
+
assert_equal new_settings.security[:signature_method], XMLSecurity::Document::RSA_SHA1
|
79
|
+
end
|
64
80
|
end
|
65
81
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
|
2
2
|
|
3
|
+
require 'onelogin/ruby-saml/slo_logoutresponse'
|
4
|
+
|
3
5
|
class SloLogoutresponseTest < Minitest::Test
|
4
6
|
|
5
7
|
describe "SloLogoutresponse" do
|
@@ -65,7 +67,7 @@ class SloLogoutresponseTest < Minitest::Test
|
|
65
67
|
assert_match /<samlp:StatusMessage>Custom Logout Message<\/samlp:StatusMessage>/, inflated
|
66
68
|
end
|
67
69
|
|
68
|
-
describe "when the settings indicate to sign (
|
70
|
+
describe "when the settings indicate to sign (embedded) logout response" do
|
69
71
|
it "create a signed logout response" do
|
70
72
|
settings = OneLogin::RubySaml::Settings.new
|
71
73
|
settings.compress_response = false
|
@@ -81,7 +83,7 @@ class SloLogoutresponseTest < Minitest::Test
|
|
81
83
|
response_xml = Base64.decode64(params["SAMLResponse"])
|
82
84
|
assert_match %r[<ds:SignatureValue>([a-zA-Z0-9/+=]+)</ds:SignatureValue>], response_xml
|
83
85
|
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#
|
86
|
+
response_xml =~ /<ds:DigestMethod Algorithm='http:\/\/www.w3.org\/2000\/09\/xmldsig#sha1'\/>/
|
85
87
|
end
|
86
88
|
|
87
89
|
it "create a signed logout response with 256 digest and signature methods" do
|
@@ -90,7 +92,7 @@ class SloLogoutresponseTest < Minitest::Test
|
|
90
92
|
settings.idp_slo_target_url = "http://example.com?field=value"
|
91
93
|
settings.security[:logout_responses_signed] = true
|
92
94
|
settings.security[:embed_sign] = true
|
93
|
-
settings.security[:signature_method] = XMLSecurity::Document::
|
95
|
+
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
|
94
96
|
settings.security[:digest_method] = XMLSecurity::Document::SHA512
|
95
97
|
settings.certificate = ruby_saml_cert_text
|
96
98
|
settings.private_key = ruby_saml_key_text
|
@@ -105,29 +107,57 @@ class SloLogoutresponseTest < Minitest::Test
|
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
108
|
-
describe "when the settings indicate to sign the logout response" do
|
109
|
-
|
110
|
-
settings = OneLogin::RubySaml::Settings.new
|
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"
|
114
|
-
settings.security[:logout_responses_signed] = true
|
115
|
-
settings.security[:embed_sign] = false
|
116
|
-
settings.
|
117
|
-
settings.
|
118
|
-
|
110
|
+
describe "#create_params when the settings indicate to sign the logout response" do
|
111
|
+
def setup
|
112
|
+
@settings = OneLogin::RubySaml::Settings.new
|
113
|
+
@settings.compress_response = false
|
114
|
+
@settings.idp_slo_target_url = "http://example.com?field=value"
|
115
|
+
@settings.assertion_consumer_service_binding = "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST-SimpleSign"
|
116
|
+
@settings.security[:logout_responses_signed] = true
|
117
|
+
@settings.security[:embed_sign] = false
|
118
|
+
@settings.certificate = ruby_saml_cert_text
|
119
|
+
@settings.private_key = ruby_saml_key_text
|
120
|
+
@cert = OpenSSL::X509::Certificate.new(ruby_saml_cert_text)
|
121
|
+
@request = OneLogin::RubySaml::SloLogoutrequest.new(logout_request_document)
|
122
|
+
end
|
119
123
|
|
120
|
-
|
121
|
-
|
124
|
+
it "create a signature parameter with RSA_SHA1 and validate it" do
|
125
|
+
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
|
126
|
+
|
127
|
+
params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(@settings, @request.id, "Custom Logout Message", :RelayState => 'http://example.com')
|
128
|
+
assert params['SAMLResponse']
|
129
|
+
assert params[:RelayState]
|
122
130
|
assert params['Signature']
|
123
|
-
|
131
|
+
assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA1
|
124
132
|
|
125
|
-
|
126
|
-
|
127
|
-
|
133
|
+
query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
|
134
|
+
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
|
135
|
+
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
|
136
|
+
|
137
|
+
signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
|
138
|
+
assert_equal signature_algorithm, OpenSSL::Digest::SHA1
|
139
|
+
assert @cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
|
140
|
+
end
|
141
|
+
|
142
|
+
it "create a signature parameter with RSA_SHA256 and validate it" do
|
143
|
+
@settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA256
|
144
|
+
|
145
|
+
params = OneLogin::RubySaml::SloLogoutresponse.new.create_params(@settings, @request.id, "Custom Logout Message", :RelayState => 'http://example.com')
|
146
|
+
assert params['SAMLResponse']
|
147
|
+
assert params[:RelayState]
|
128
148
|
assert params['Signature']
|
129
|
-
|
149
|
+
|
150
|
+
assert_equal params['SigAlg'], XMLSecurity::Document::RSA_SHA256
|
151
|
+
|
152
|
+
query_string = "SAMLResponse=#{CGI.escape(params['SAMLResponse'])}"
|
153
|
+
query_string << "&RelayState=#{CGI.escape(params[:RelayState])}"
|
154
|
+
query_string << "&SigAlg=#{CGI.escape(params['SigAlg'])}"
|
155
|
+
|
156
|
+
signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
|
157
|
+
assert_equal signature_algorithm, OpenSSL::Digest::SHA256
|
158
|
+
assert @cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
|
130
159
|
end
|
160
|
+
|
131
161
|
end
|
132
162
|
end
|
133
163
|
end
|
data/test/test_helper.rb
CHANGED
data/test/xml_security_test.rb
CHANGED
@@ -78,7 +78,44 @@ class XmlSecurityTest < Minitest::Test
|
|
78
78
|
end
|
79
79
|
end
|
80
80
|
|
81
|
-
describe "Algorithms" do
|
81
|
+
describe "Fingerprint Algorithms" do
|
82
|
+
let(:response_fingerprint_test) { OneLogin::RubySaml::Response.new(fixture(:adfs_response_sha1, false)) }
|
83
|
+
|
84
|
+
it "validate using SHA1" do
|
85
|
+
sha1_fingerprint = "F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72"
|
86
|
+
sha1_fingerprint_downcase = "f13c6b80905a030e6c913e5d15faddb016454872"
|
87
|
+
|
88
|
+
assert response_fingerprint_test.document.validate_document(sha1_fingerprint)
|
89
|
+
assert response_fingerprint_test.document.validate_document(sha1_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA1)
|
90
|
+
|
91
|
+
assert response_fingerprint_test.document.validate_document(sha1_fingerprint_downcase)
|
92
|
+
assert response_fingerprint_test.document.validate_document(sha1_fingerprint_downcase, true, :fingerprint_alg => XMLSecurity::Document::SHA1)
|
93
|
+
end
|
94
|
+
|
95
|
+
it "validate using SHA256" do
|
96
|
+
sha256_fingerprint = "C4:C6:BD:41:EC:AD:57:97:CE:7B:7D:80:06:C3:E4:30:53:29:02:0B:DD:2D:47:02:9E:BD:85:AD:93:02:45:21"
|
97
|
+
|
98
|
+
assert !response_fingerprint_test.document.validate_document(sha256_fingerprint)
|
99
|
+
assert response_fingerprint_test.document.validate_document(sha256_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA256)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "validate using SHA384" do
|
103
|
+
sha384_fingerprint = "98:FE:17:90:31:E7:68:18:8A:65:4D:DA:F5:76:E2:09:97:BE:8B:E3:7E:AA:8D:63:64:7C:0C:38:23:9A:AC:A2:EC:CE:48:A6:74:4D:E0:4C:50:80:40:B4:8D:55:14:14"
|
104
|
+
|
105
|
+
assert !response_fingerprint_test.document.validate_document(sha384_fingerprint)
|
106
|
+
assert response_fingerprint_test.document.validate_document(sha384_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA384)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "validate using SHA512" do
|
110
|
+
sha512_fingerprint = "5A:AE:BA:D0:BA:9D:1E:25:05:01:1E:1A:C9:E9:FF:DB:ED:FA:6E:F7:52:EB:45:49:BD:DB:06:D8:A3:7E:CC:63:3A:04:A2:DD:DF:EE:61:05:D9:58:95:2A:77:17:30:4B:EB:4A:9F:48:4A:44:1C:D0:9E:0B:1E:04:77:FD:A3:D2"
|
111
|
+
|
112
|
+
assert !response_fingerprint_test.document.validate_document(sha512_fingerprint)
|
113
|
+
assert response_fingerprint_test.document.validate_document(sha512_fingerprint, true, :fingerprint_alg => XMLSecurity::Document::SHA512)
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "Signature Algorithms" do
|
82
119
|
it "validate using SHA1" do
|
83
120
|
@document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha1, false))
|
84
121
|
assert @document.validate_document("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
|
@@ -157,7 +194,7 @@ class XmlSecurityTest < Minitest::Test
|
|
157
194
|
|
158
195
|
# verify our signature
|
159
196
|
signed_doc = XMLSecurity::SignedDocument.new(request.to_s)
|
160
|
-
signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
|
197
|
+
assert signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
|
161
198
|
end
|
162
199
|
|
163
200
|
it "sign a LogoutRequest" do
|
@@ -173,7 +210,7 @@ class XmlSecurityTest < Minitest::Test
|
|
173
210
|
|
174
211
|
# verify our signature
|
175
212
|
signed_doc = XMLSecurity::SignedDocument.new(request.to_s)
|
176
|
-
signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
|
213
|
+
assert signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
|
177
214
|
end
|
178
215
|
|
179
216
|
it "sign a LogoutResponse" do
|
@@ -189,7 +226,7 @@ class XmlSecurityTest < Minitest::Test
|
|
189
226
|
|
190
227
|
# verify our signature
|
191
228
|
signed_doc = XMLSecurity::SignedDocument.new(response.to_s)
|
192
|
-
signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
|
229
|
+
assert signed_doc.validate_document(ruby_saml_cert_fingerprint, false)
|
193
230
|
end
|
194
231
|
end
|
195
232
|
|