Skip to content

Commit c66b940

Browse files
committed
Test verification of SAML message signatures
Test that providing raw URI components allows correct signature verification where the URI-encoding differs from that generated by ruby-saml itself.
1 parent 1cf9ad2 commit c66b940

File tree

1 file changed

+72
-0
lines changed

1 file changed

+72
-0
lines changed

test/slo_logoutrequest_test.rb

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,78 @@ class RubySamlTest < Minitest::Test
322322
logout_request_sign_test.send(:validate_signature)
323323
end
324324
end
325+
326+
it "raise when get_params encoding differs from what this library generates" do
327+
# Use Logoutrequest only to build the SAMLRequest parameter.
328+
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
329+
settings.soft = false
330+
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, "RelayState" => "http://example.com")
331+
# Assemble query string.
332+
query = OneLogin::RubySaml::Utils.build_query(
333+
type: 'SAMLRequest',
334+
data: params['SAMLRequest'],
335+
relay_state: params['RelayState'],
336+
sig_alg: params['SigAlg'],
337+
)
338+
# Modify the query string so that it encodes the same values,
339+
# but with different percent-encoding. Sanity-check that they
340+
# really are equialent before moving on.
341+
original_query = query.dup
342+
query.gsub!("example", "ex%61mple")
343+
refute_equal(query, original_query)
344+
assert_equal(CGI.unescape(query), CGI.unescape(original_query))
345+
# Make normalised signature based on our modified params.
346+
sign_algorithm = XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method])
347+
signature = settings.get_sp_key.sign(sign_algorithm.new, query)
348+
params['Signature'] = Base64.encode64(signature).gsub(/\n/, "")
349+
# Construct SloLogoutrequest and ask it to validate the signature.
350+
# It will do it incorrectly, because it will compute it based on re-encoded
351+
# query parameters, rather than their original encodings.
352+
options = {}
353+
options[:get_params] = params
354+
options[:settings] = settings
355+
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
356+
assert_raises(OneLogin::RubySaml::ValidationError, "Invalid Signature on Logout Request") do
357+
logout_request_sign_test.send(:validate_signature)
358+
end
359+
end
360+
361+
it "return true even if raw_get_params encoding differs from what this library generates" do
362+
# Use Logoutrequest only to build the SAMLRequest parameter.
363+
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
364+
settings.soft = false
365+
params = OneLogin::RubySaml::Logoutrequest.new.create_params(settings, "RelayState" => "http://example.com")
366+
# Assemble query string.
367+
query = OneLogin::RubySaml::Utils.build_query(
368+
type: 'SAMLRequest',
369+
data: params['SAMLRequest'],
370+
relay_state: params['RelayState'],
371+
sig_alg: params['SigAlg'],
372+
)
373+
# Modify the query string so that it encodes the same values,
374+
# but with different percent-encoding. Sanity-check that they
375+
# really are equialent before moving on.
376+
original_query = query.dup
377+
query.gsub!("example", "ex%61mple")
378+
refute_equal(query, original_query)
379+
assert_equal(CGI.unescape(query), CGI.unescape(original_query))
380+
# Make normalised signature based on our modified params.
381+
sign_algorithm = XMLSecurity::BaseDocument.new.algorithm(settings.security[:signature_method])
382+
signature = settings.get_sp_key.sign(sign_algorithm.new, query)
383+
params['Signature'] = Base64.encode64(signature).gsub(/\n/, "")
384+
# Construct SloLogoutrequest and ask it to validate the signature.
385+
# Provide the altered parameter in its raw URI-encoded form,
386+
# so that we don't have to guess the value that contributed to the signature.
387+
options = {}
388+
options[:get_params] = params
389+
options[:get_params].delete("RelayState")
390+
options[:raw_get_params] = {
391+
"RelayState" => "http%3A%2F%2Fex%61mple.com",
392+
}
393+
options[:settings] = settings
394+
logout_request_sign_test = OneLogin::RubySaml::SloLogoutrequest.new(params['SAMLRequest'], options)
395+
assert logout_request_sign_test.send(:validate_signature)
396+
end
325397
end
326398

327399
describe "#validate_signature with multiple idp certs" do

0 commit comments

Comments
 (0)