Skip to content

Commit f6b949d

Browse files
committed
Fix #437. Creating AuthRequests/LogoutRequests/LogoutResponses with nil RelayState sends empty RelayState URL param
1 parent 25be1b9 commit f6b949d

7 files changed

Lines changed: 65 additions & 8 deletions

File tree

lib/onelogin/ruby-saml/authrequest.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,11 @@ def create_params(settings, params={})
5151
# conflicts so this line will solve them.
5252
relay_state = params[:RelayState] || params['RelayState']
5353

54+
if relay_state.nil?
55+
params.delete(:RelayState)
56+
params.delete('RelayState')
57+
end
58+
5459
request_doc = create_authentication_xml_doc(settings)
5560
request_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values
5661

@@ -158,7 +163,7 @@ def create_xml_document(settings)
158163

159164
def sign_document(document, settings)
160165
# embed signature
161-
if settings.security[:authn_requests_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
166+
if settings.security[:authn_requests_signed] && settings.private_key && settings.certificate && settings.security[:embed_sign]
162167
private_key = settings.get_sp_key
163168
cert = settings.get_sp_cert
164169
document.sign_document(private_key, cert, settings.security[:signature_method], settings.security[:digest_method])

lib/onelogin/ruby-saml/logoutrequest.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ def create_params(settings, params={})
4747
# conflicts so this line will solve them.
4848
relay_state = params[:RelayState] || params['RelayState']
4949

50+
if relay_state.nil?
51+
params.delete(:RelayState)
52+
params.delete('RelayState')
53+
end
54+
5055
request_doc = create_logout_request_xml_doc(settings)
5156
request_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values
5257

lib/onelogin/ruby-saml/slo_logoutresponse.rb

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ def create_params(settings, request_id = nil, logout_message = nil, params = {})
5353
# conflicts so this line will solve them.
5454
relay_state = params[:RelayState] || params['RelayState']
5555

56+
if relay_state.nil?
57+
params.delete(:RelayState)
58+
params.delete('RelayState')
59+
end
60+
5661
response_doc = create_logout_response_xml_doc(settings, request_id, logout_message)
5762
response_doc.context[:attribute_quote] = :quote if settings.double_quote_xml_attribute_values
5863

@@ -108,7 +113,7 @@ def create_logout_response_xml_doc(settings, request_id = nil, logout_message =
108113
issuer = root.add_element "saml:Issuer"
109114
issuer.text = settings.issuer
110115
end
111-
116+
112117
# add success message
113118
status = root.add_element 'samlp:Status'
114119

test/logoutrequest_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,20 @@ class RequestTest < Minitest::Test
2828
assert_match /&foo=bar$/, unauth_url
2929
end
3030

31+
it "RelayState cases" do
32+
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :RelayState => nil })
33+
assert !unauth_url.include?('RelayState')
34+
35+
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :RelayState => "http://example.com" })
36+
assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
37+
38+
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { 'RelayState' => nil })
39+
assert !unauth_url.include?('RelayState')
40+
41+
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { 'RelayState' => "http://example.com" })
42+
assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
43+
end
44+
3145
it "set sessionindex" do
3246
settings.idp_slo_target_url = "http://example.com"
3347
sessionidx = OneLogin::RubySaml::Utils.uuid

test/request_test.rb

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,20 @@ class RequestTest < Minitest::Test
129129
assert_match /&hello=$/, auth_url
130130
end
131131

132+
it "RelayState cases" do
133+
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :RelayState => nil })
134+
assert !auth_url.include?('RelayState')
135+
136+
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { :RelayState => "http://example.com" })
137+
assert auth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
138+
139+
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { 'RelayState' => nil })
140+
assert !auth_url.include?('RelayState')
141+
142+
auth_url = OneLogin::RubySaml::Authrequest.new.create(settings, { 'RelayState' => "http://example.com" })
143+
assert auth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
144+
end
145+
132146
describe "when the target url is not set" do
133147
before do
134148
settings.idp_sso_target_url = nil
@@ -235,7 +249,7 @@ class RequestTest < Minitest::Test
235249
settings.certificate = ruby_saml_cert_text
236250
settings.private_key = ruby_saml_key_text
237251
end
238-
252+
239253
it "create a signature parameter with RSA_SHA1 and validate it" do
240254
settings.security[:signature_method] = XMLSecurity::Document::RSA_SHA1
241255

@@ -268,7 +282,7 @@ class RequestTest < Minitest::Test
268282

269283
signature_algorithm = XMLSecurity::BaseDocument.new.algorithm(params['SigAlg'])
270284
assert_equal signature_algorithm, OpenSSL::Digest::SHA256
271-
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
285+
assert cert.public_key.verify(signature_algorithm.new, Base64.decode64(params['Signature']), query_string)
272286
end
273287
end
274288

test/slo_logoutresponse_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,20 @@ class SloLogoutresponseTest < Minitest::Test
3737
assert_match /&RelayState=http%3A%2F%2Fidp.example.com$/, unauth_url
3838
end
3939

40+
it "RelayState cases" do
41+
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :RelayState => nil })
42+
assert !unauth_url.include?('RelayState')
43+
44+
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { :RelayState => "http://example.com" })
45+
assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
46+
47+
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { 'RelayState' => nil })
48+
assert !unauth_url.include?('RelayState')
49+
50+
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id, nil, { 'RelayState' => "http://example.com" })
51+
assert unauth_url.include?('&RelayState=http%3A%2F%2Fexample.com')
52+
end
53+
4054
it "set InResponseTo to the ID from the logout request" do
4155
unauth_url = OneLogin::RubySaml::SloLogoutresponse.new.create(settings, logout_request.id)
4256

test/test_helper.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,15 +117,15 @@ def response_document_encrypted_nameid
117117
end
118118

119119
def signed_message_encrypted_unsigned_assertion
120-
@signed_message_encrypted_unsigned_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_unsigned_assertion.xml.base64'))
120+
@signed_message_encrypted_unsigned_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_unsigned_assertion.xml.base64'))
121121
end
122122

123123
def signed_message_encrypted_signed_assertion
124-
@signed_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_signed_assertion.xml.base64'))
124+
@signed_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'signed_message_encrypted_signed_assertion.xml.base64'))
125125
end
126126

127127
def unsigned_message_encrypted_signed_assertion
128-
@unsigned_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'unsigned_message_encrypted_signed_assertion.xml.base64'))
128+
@unsigned_message_encrypted_signed_assertion ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'unsigned_message_encrypted_signed_assertion.xml.base64'))
129129
end
130130

131131
def unsigned_message_encrypted_unsigned_assertion
@@ -145,7 +145,7 @@ def signature_fingerprint_1
145145
end
146146

147147
# certificate used on response_with_undefined_recipient
148-
def signature_1
148+
def signature_1
149149
@signature1 ||= read_certificate("certificate1")
150150
end
151151

0 commit comments

Comments
 (0)