Skip to content

Commit 10bfc7a

Browse files
Merge pull request #13 from gerardo-navarro/gerardo-navarro-adjust-relay_state_validator-behavior
Clarify SLO relay state validator boolean handling
2 parents c9150ed + d0a95cb commit 10bfc7a

File tree

3 files changed

+40
-29
lines changed

3 files changed

+40
-29
lines changed

README.md

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,11 @@ Note that when [integrating with Devise](#devise-integration), the URL path will
110110
second argument, the current Rack request. The default validator allows relative paths beginning
111111
with `/` and absolute `http` or `https` URLs, and rejects invalid URIs, protocol-relative URLs, and
112112
other schemes. Defaults generated via `:slo_default_relay_state` are assumed to be safe and skipped by
113-
this validation step. Optional.
114-
115-
```ruby
116-
config.omniauth :saml, slo_relay_state_validator: lambda { |relay_state|
117-
relay_state&.start_with?("/")
118-
}
119-
```
113+
this validation step. Optional. When set to `true`, every RelayState value is accepted. When set to
114+
`false` (or any other falsy value), every provided RelayState is rejected and the strategy falls back
115+
to the default RelayState. See the SLO relay state validator specs in
116+
[`spec/omniauth/strategies/saml_spec.rb`](spec/omniauth/strategies/saml_spec.rb) for additional
117+
examples.
120118

121119
* `:idp_sso_service_url_runtime_params` - A dynamic mapping of request params that exist
122120
during the request phase of OmniAuth that should to be sent to the IdP after a specific

lib/omniauth/strategies/saml.rb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,9 +187,10 @@ def slo_relay_state
187187

188188
def valid_slo_relay_state?(relay_state)
189189
validator = options.slo_relay_state_validator
190-
return true unless validator
191190

192-
!!call_slo_relay_state_validator(validator, relay_state)
191+
return !!call_slo_relay_state_validator(validator, relay_state) if validator.respond_to?(:call)
192+
193+
!!validator
193194
end
194195

195196
def call_slo_relay_state_validator(validator, relay_state)

spec/omniauth/strategies/saml_spec.rb

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -410,12 +410,18 @@ def post_xml(xml = :example_response, opts = {})
410410
context "when the validator option is nil" do
411411
let(:saml_options) { super().merge(slo_relay_state_validator: nil) }
412412

413-
it { is_expected.to have_attributes(location: a_string_matching(/RelayState=javascript%3Aalert%281%29/)) }
413+
it { is_expected.to have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
414414
end
415415

416416
context "when the validator option is false" do
417417
let(:saml_options) { super().merge(slo_relay_state_validator: false) }
418418

419+
it { is_expected.to have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
420+
end
421+
422+
context "when the validator option is true" do
423+
let(:saml_options) { super().merge(slo_relay_state_validator: true) }
424+
419425
it { is_expected.to have_attributes(location: a_string_matching(/RelayState=javascript%3Aalert%281%29/)) }
420426
end
421427

@@ -551,34 +557,40 @@ def test_default_relay_state(static_default_relay_state = nil, &block_default_re
551557
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
552558
end
553559

554-
context 'with a javascript relay state' do
555-
let(:params) { { RelayState: "javascript:alert(1)" } }
560+
context 'with a javascript relay state' do
561+
let(:params) { { RelayState: "javascript:alert(1)" } }
556562

557-
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
563+
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
558564

559-
context 'when the validator would reject the default' do
560-
let(:saml_options) do
561-
super().merge(slo_relay_state_validator: proc { |value| value.start_with?("https://") })
565+
context 'when the validator would reject the default' do
566+
let(:saml_options) do
567+
super().merge(slo_relay_state_validator: proc { |value| value.start_with?("https://") })
568+
end
569+
570+
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
562571
end
563572

564-
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
565-
end
573+
context 'when the validator is nil' do
574+
let(:saml_options) { super().merge(slo_relay_state_validator: nil) }
566575

567-
context 'when the validator is nil' do
568-
let(:saml_options) { super().merge(slo_relay_state_validator: nil) }
576+
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
577+
end
569578

570-
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=javascript%3Aalert%281%29/)) }
571-
end
579+
context 'when the validator is false' do
580+
let(:saml_options) { super().merge(slo_relay_state_validator: false) }
572581

573-
context 'when the validator is false' do
574-
let(:saml_options) { super().merge(slo_relay_state_validator: false) }
582+
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
583+
end
575584

576-
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=javascript%3Aalert%281%29/)) }
577-
end
585+
context 'when the validator is true' do
586+
let(:saml_options) { super().merge(slo_relay_state_validator: true) }
578587

579-
context 'when the validator returns false' do
580-
let(:saml_options) do
581-
super().merge(slo_relay_state_validator: proc { |state| state == "/signed-out" })
588+
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=javascript%3Aalert%281%29/)) }
589+
end
590+
591+
context 'when the validator returns false' do
592+
let(:saml_options) do
593+
super().merge(slo_relay_state_validator: proc { |state| state == "/signed-out" })
582594
end
583595

584596
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }

0 commit comments

Comments
 (0)