Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Commit

Permalink
Fix SAML-Toolkits#437. Creating AuthRequests/LogoutRequests/LogoutRes…
Browse files Browse the repository at this point in the history
…ponses with nil RelayState sends empty RelayState URL param
  • Loading branch information
pitbulk committed Apr 23, 2018
1 parent 25be1b9 commit f6b949d
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 8 deletions.
7 changes: 6 additions & 1 deletion lib/onelogin/ruby-saml/authrequest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ def create_params(settings, params={})
# conflicts so this line will solve them.
relay_state = params[:RelayState] || params['RelayState']

if relay_state.nil?
params.delete(:RelayState)
params.delete('RelayState')
end

request_doc = create_authentication_xml_doc(settings)
request_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values

Expand Down Expand Up @@ -158,7 +163,7 @@ def create_xml_document(settings)

def sign_document(document, settings)
# embed signature
if settings.security[:authn_requests_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
if settings.security[:authn_requests_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
private_key = settings.get_sp_key
cert = settings.get_sp_cert
document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])
Expand Down
5 changes: 5 additions & 0 deletions lib/onelogin/ruby-saml/logoutrequest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,11 @@ def create_params(settings, params={})
# conflicts so this line will solve them.
relay_state = params[:RelayState] || params['RelayState']

if relay_state.nil?
params.delete(:RelayState)
params.delete('RelayState')
end

request_doc = create_logout_request_xml_doc(settings)
request_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values

Expand Down
7 changes: 6 additions & 1 deletion lib/onelogin/ruby-saml/slo_logoutresponse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ def create_params(settings, request_id = nil, logout_message = nil, params = {})
# conflicts so this line will solve them.
relay_state = params[:RelayState] || params['RelayState']

if relay_state.nil?
params.delete(:RelayState)
params.delete('RelayState')
end

response_doc = create_logout_response_xml_doc(settings, request_id, logout_message)
response_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values

Expand Down Expand Up @@ -108,7 +113,7 @@ def create_logout_response_xml_doc(settings, request_id = nil, logout_message =
issuer = root.add_element "saml:Issuer"
issuer.text = settings.issuer
end

# add success message
status = root.add_element 'samlp:Status'

Expand Down
14 changes: 14 additions & 0 deletions test/logoutrequest_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,20 @@ class RequestTest < Minitest::Test
assert_match /&foo=bar$/, unauth_url
end

it "RelayState cases" do
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :RelayState => nil })
assert !unauth_url.include?('RelayState')

unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :RelayState => "http://example.com" })
assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')

unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { 'RelayState' => nil })
assert !unauth_url.include?('RelayState')

unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { 'RelayState' => "http://example.com" })
assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
end

it "set sessionindex" do
settings.idp_slo_target_url = "http://example.com"
sessionidx = OneLogin::RubySaml::Utils.uuid
Expand Down
18 changes: 16 additions & 2 deletions test/request_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,20 @@ class RequestTest < Minitest::Test
assert_match /&hello=$/, auth_url
end

it "RelayState cases" do
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :RelayState => nil })
assert !auth_url.include?('RelayState')

auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :RelayState => "http://example.com" })
assert auth_url.include?('&RelayState=http%3A%2F%2Fexample.com')

auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { 'RelayState' => nil })
assert !auth_url.include?('RelayState')

auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { 'RelayState' => "http://example.com" })
assert auth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
end

describe "when the target url is not set" do
before do
settings.idp_sso_target_url = nil
Expand Down Expand Up @@ -235,7 +249,7 @@ class RequestTest < Minitest::Test
settings.certificate = ruby_saml_cert_text
settings.private_key = ruby_saml_key_text
end

it "create a signature parameter with RSA_SHA1 and validate it" do
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1

Expand Down Expand Up @@ -268,7 +282,7 @@ class RequestTest < Minitest::Test

signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
assert_equal signature_algorithm, OpenSSL::Digest::SHA256
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
end
end

Expand Down
14 changes: 14 additions & 0 deletions test/slo_logoutresponse_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ class SloLogoutresponseTest < Minitest::Test
assert_match /&RelayState=http%3A%2F%2Fidp.example.com$/, unauth_url
end

it "RelayState cases" do
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :RelayState => nil })
assert !unauth_url.include?('RelayState')

unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :RelayState => "http://example.com" })
assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')

unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { 'RelayState' => nil })
assert !unauth_url.include?('RelayState')

unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { 'RelayState' => "http://example.com" })
assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
end

it "set InResponseTo to the ID from the logout request" do
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id)

Expand Down
8 changes: 4 additions & 4 deletions test/test_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -117,15 +117,15 @@ def response_document_encrypted_nameid
end

def signed_message_encrypted_unsigned_assertion
@signed_message_encrypted_unsigned_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_unsigned_assertion.xml.base64'))
@signed_message_encrypted_unsigned_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_unsigned_assertion.xml.base64'))
end

def signed_message_encrypted_signed_assertion
@signed_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_signed_assertion.xml.base64'))
@signed_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_signed_assertion.xml.base64'))
end

def unsigned_message_encrypted_signed_assertion
@unsigned_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'unsigned_message_encrypted_signed_assertion.xml.base64'))
@unsigned_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'unsigned_message_encrypted_signed_assertion.xml.base64'))
end

def unsigned_message_encrypted_unsigned_assertion
Expand All @@ -145,7 +145,7 @@ def signature_fingerprint_1
end

# certificate used on response_with_undefined_recipient
def signature_1
def signature_1
@signature1 ||= read_certificate("certificate1")
end

Expand Down

0 comments on commit f6b949d

Please sign in to comment.