@@ -283,6 +283,80 @@ class RubySamlTest < Minitest::Test
283283 assert_raises ( OneLogin ::RubySaml ::ValidationError ) { logoutresponse . send ( :validate_signature ) }
284284 assert logoutresponse . errors . include? "Invalid Signature on Logout Response"
285285 end
286+
287+ it "raise when get_params encoding differs from what this library generates" do
288+ settings . security [ :signature_method ] = XMLSecurity ::Document ::RSA_SHA1
289+ settings . soft = false
290+ options = { }
291+ options [ :get_params ] = params
292+ options [ :get_params ] [ 'RelayState' ] = 'http://example.com'
293+ logoutresponse = OneLogin ::RubySaml ::Logoutresponse . new ( params [ 'SAMLResponse' ] , settings , options )
294+ # Assemble query string.
295+ query = OneLogin ::RubySaml ::Utils . build_query (
296+ type : 'SAMLResponse' ,
297+ data : params [ 'SAMLResponse' ] ,
298+ relay_state : params [ 'RelayState' ] ,
299+ sig_alg : params [ 'SigAlg' ] ,
300+ )
301+ # Modify the query string so that it encodes the same values,
302+ # but with different percent-encoding. Sanity-check that they
303+ # really are equialent before moving on.
304+ original_query = query . dup
305+ query . gsub! ( "example" , "ex%61mple" )
306+ refute_equal ( query , original_query )
307+ assert_equal ( CGI . unescape ( query ) , CGI . unescape ( original_query ) )
308+ # Make normalised signature based on our modified params.
309+ sign_algorithm = XMLSecurity ::BaseDocument . new . algorithm ( settings . security [ :signature_method ] )
310+ signature = settings . get_sp_key . sign ( sign_algorithm . new , query )
311+ params [ 'Signature' ] = Base64 . encode64 ( signature ) . gsub ( /\n / , "" )
312+ # Re-create the Logoutresponse based on these modified parameters,
313+ # and ask it to validate the signature. It will do it incorrectly,
314+ # because it will compute it based on re-encoded query parameters,
315+ # rather than their original encodings.
316+ options [ :get_params ] = params
317+ logoutresponse = OneLogin ::RubySaml ::Logoutresponse . new ( params [ 'SAMLResponse' ] , settings , options )
318+ assert_raises ( OneLogin ::RubySaml ::ValidationError , "Invalid Signature on Logout Request" ) do
319+ logoutresponse . send ( :validate_signature )
320+ end
321+ end
322+
323+ it "return true even if raw_get_params encoding differs from what this library generates" do
324+ settings . security [ :signature_method ] = XMLSecurity ::Document ::RSA_SHA1
325+ settings . soft = false
326+ options = { }
327+ options [ :get_params ] = params
328+ options [ :get_params ] [ 'RelayState' ] = 'http://example.com'
329+ logoutresponse = OneLogin ::RubySaml ::Logoutresponse . new ( params [ 'SAMLResponse' ] , settings , options )
330+ # Assemble query string.
331+ query = OneLogin ::RubySaml ::Utils . build_query (
332+ type : 'SAMLResponse' ,
333+ data : params [ 'SAMLResponse' ] ,
334+ relay_state : params [ 'RelayState' ] ,
335+ sig_alg : params [ 'SigAlg' ] ,
336+ )
337+ # Modify the query string so that it encodes the same values,
338+ # but with different percent-encoding. Sanity-check that they
339+ # really are equialent before moving on.
340+ original_query = query . dup
341+ query . gsub! ( "example" , "ex%61mple" )
342+ refute_equal ( query , original_query )
343+ assert_equal ( CGI . unescape ( query ) , CGI . unescape ( original_query ) )
344+ # Make normalised signature based on our modified params.
345+ sign_algorithm = XMLSecurity ::BaseDocument . new . algorithm ( settings . security [ :signature_method ] )
346+ signature = settings . get_sp_key . sign ( sign_algorithm . new , query )
347+ params [ 'Signature' ] = Base64 . encode64 ( signature ) . gsub ( /\n / , "" )
348+ # Re-create the Logoutresponse based on these modified parameters,
349+ # and ask it to validate the signature. Provide the altered parameter
350+ # in its raw URI-encoded form, so that we don't have to guess the value
351+ # that contributed to the signature.
352+ options [ :get_params ] = params
353+ options [ :get_params ] . delete ( "RelayState" )
354+ options [ :raw_get_params ] = {
355+ "RelayState" => "http%3A%2F%2Fex%61mple.com" ,
356+ }
357+ logoutresponse = OneLogin ::RubySaml ::Logoutresponse . new ( params [ 'SAMLResponse' ] , settings , options )
358+ assert logoutresponse . send ( :validate_signature )
359+ end
286360 end
287361
288362 describe "#validate_signature" do
0 commit comments