Skip to content

Commit 8bfba33

Browse files
Merge branch 'gerardo-navarro-implement-slo-relay-state-validator' into gerardo-navarro-restrict-default-to-relative-paths
2 parents 06522cb + 10bfc7a commit 8bfba33

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 only relative paths beginning
111111
with `/` and rejects absolute URLs, invalid URIs, protocol-relative URLs, and other schemes. Defaults
112112
generated via `:slo_default_relay_state` are assumed to be safe and skipped by this validation step.
113-
Optional.
114-
115-
```ruby
116-
config.omniauth :saml, slo_relay_state_validator: lambda { |relay_state|
117-
relay_state&.start_with?("/")
118-
}
119-
```
113+
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
@@ -185,9 +185,10 @@ def slo_relay_state
185185

186186
def valid_slo_relay_state?(relay_state)
187187
validator = options.slo_relay_state_validator
188-
return true unless validator
189188

190-
!!call_slo_relay_state_validator(validator, relay_state)
189+
return !!call_slo_relay_state_validator(validator, relay_state) if validator.respond_to?(:call)
190+
191+
!!validator
191192
end
192193

193194
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
@@ -406,12 +406,18 @@ def post_xml(xml = :example_response, opts = {})
406406
context "when the validator option is nil" do
407407
let(:saml_options) { super().merge(slo_relay_state_validator: nil) }
408408

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

412412
context "when the validator option is false" do
413413
let(:saml_options) { super().merge(slo_relay_state_validator: false) }
414414

415+
it { is_expected.to have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
416+
end
417+
418+
context "when the validator option is true" do
419+
let(:saml_options) { super().merge(slo_relay_state_validator: true) }
420+
415421
it { is_expected.to have_attributes(location: a_string_matching(/RelayState=javascript%3Aalert%281%29/)) }
416422
end
417423

@@ -547,34 +553,40 @@ def test_default_relay_state(static_default_relay_state = nil, &block_default_re
547553
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
548554
end
549555

550-
context 'with a javascript relay state' do
551-
let(:params) { { RelayState: "javascript:alert(1)" } }
556+
context 'with a javascript relay state' do
557+
let(:params) { { RelayState: "javascript:alert(1)" } }
552558

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

555-
context 'when the validator would reject the default' do
556-
let(:saml_options) do
557-
super().merge(slo_relay_state_validator: proc { |value| value.start_with?("https://") })
561+
context 'when the validator would reject the default' do
562+
let(:saml_options) do
563+
super().merge(slo_relay_state_validator: proc { |value| value.start_with?("https://") })
564+
end
565+
566+
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
558567
end
559568

560-
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
561-
end
569+
context 'when the validator is nil' do
570+
let(:saml_options) { super().merge(slo_relay_state_validator: nil) }
562571

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

566-
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=javascript%3Aalert%281%29/)) }
567-
end
575+
context 'when the validator is false' do
576+
let(:saml_options) { super().merge(slo_relay_state_validator: false) }
568577

569-
context 'when the validator is false' do
570-
let(:saml_options) { super().merge(slo_relay_state_validator: false) }
578+
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=%2Fsigned-out/)) }
579+
end
571580

572-
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=javascript%3Aalert%281%29/)) }
573-
end
581+
context 'when the validator is true' do
582+
let(:saml_options) { super().merge(slo_relay_state_validator: true) }
574583

575-
context 'when the validator returns false' do
576-
let(:saml_options) do
577-
super().merge(slo_relay_state_validator: proc { |state| state == "/signed-out" })
584+
it { is_expected.to be_redirect.and have_attributes(location: a_string_matching(/RelayState=javascript%3Aalert%281%29/)) }
585+
end
586+
587+
context 'when the validator returns false' do
588+
let(:saml_options) do
589+
super().merge(slo_relay_state_validator: proc { |state| state == "/signed-out" })
578590
end
579591

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

0 commit comments

Comments
 (0)