ruby-saml 0.9.1 → 0.9.2
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.
- 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
|
|