diff --git a/README.md b/README.md index 9cefeaf..7520049 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,8 @@ Note that when [integrating with Devise](#devise-integration), the URL path will instance will be passed to this callable if it has an arity of 1. If the value is a string, the string will be returned, when the `RelayState` is called. Optional. +* `:slo_enabled` - Enables or disables Single Logout (SLO). Set to `false` to disable SLO. Defaults to `true`. Optional. + * `:idp_sso_service_url_runtime_params` - A dynamic mapping of request params that exist during the request phase of OmniAuth that should to be sent to the IdP after a specific mapping. So for example, a param `original_request_param` with value `original_param_value`, @@ -112,7 +114,7 @@ Note that when [integrating with Devise](#devise-integration), the URL path will * `:idp_cert` - The identity provider's certificate in PEM format. Takes precedence over the fingerprint option below. This option or `:idp_cert_multi` or `:idp_cert_fingerprint` must be present. - + * `:idp_cert_multi` - Multiple identity provider certificates in PEM format. Takes precedence over the fingerprint option below. This option `:idp_cert` or `:idp_cert_fingerprint` must be present. @@ -192,7 +194,9 @@ Single Logout can be Service Provider initiated or Identity Provider initiated. For SP initiated logout, the `idp_slo_service_url` option must be set to the logout url on the IdP, and users directed to `user_saml_omniauth_authorize_path + '/spslo'` after logging out locally. For IdP initiated logout, logout requests from the IdP should go to `/auth/saml/slo` (this can be -advertised in metadata by setting the `single_logout_service_url` config option). +advertised in metadata by setting the `single_logout_service_url` config option). If you wish to +disable Single Logout entirely (both SP and IdP initiated), set `:slo_enabled => false`; the `/auth/saml/slo` +and `/auth/saml/spslo` endpoints will then respond with HTTP 501 Not Implemented. When using Devise as an authentication solution, the SP initiated flow can be integrated in the `SessionsController#destroy` action. diff --git a/lib/omniauth/strategies/saml.rb b/lib/omniauth/strategies/saml.rb index 014a607..ceeb292 100644 --- a/lib/omniauth/strategies/saml.rb +++ b/lib/omniauth/strategies/saml.rb @@ -28,6 +28,7 @@ def self.inherited(subclass) last_name: ["last_name", "lastname", "lastName"] } option :slo_default_relay_state + option :slo_enabled, true option :uid_attribute option :idp_slo_session_destroy, proc { |_env, session| session.clear } @@ -73,8 +74,12 @@ def other_phase if on_subpath?(:metadata) other_phase_for_metadata elsif on_subpath?(:slo) + return slo_disabled_response unless slo_enabled? + other_phase_for_slo elsif on_subpath?(:spslo) + return slo_disabled_response unless slo_enabled? + other_phase_for_spslo else call_app! @@ -259,6 +264,14 @@ def other_phase_for_spslo end end + def slo_enabled? + !!options[:slo_enabled] + end + + def slo_disabled_response + Rack::Response.new("Not Implemented", 501, { "Content-Type" => "text/html" }).finish + end + def add_request_attributes_to(settings) settings.attribute_consuming_service.service_name options.attribute_service_name settings.sp_entity_id = options.sp_entity_id diff --git a/spec/omniauth/strategies/saml_spec.rb b/spec/omniauth/strategies/saml_spec.rb index c807da0..a662a84 100644 --- a/spec/omniauth/strategies/saml_spec.rb +++ b/spec/omniauth/strategies/saml_spec.rb @@ -268,7 +268,6 @@ def post_xml(xml = :example_response, opts = {}) expect(last_request.env['omniauth.error'].message).to eq("SAML response missing 'missing_attribute' attribute") end end - end describe 'POST /auth/saml/slo' do @@ -333,6 +332,18 @@ def post_xml(xml = :example_response, opts = {}) end end end + + context "when SLO is disabled" do + before do + saml_options[:slo_enabled] = false + post "/auth/saml/slo" + end + + it "should return not implemented" do + expect(last_response.status).to eq 501 + expect(last_response.body).to eq "Not Implemented" + end + end end describe 'POST /auth/saml/spslo' do @@ -368,6 +379,18 @@ def test_default_relay_state(static_default_relay_state = nil, &block_default_re expect(last_response.status).to eq 501 expect(last_response.body).to match /Not Implemented/ end + + context "when SLO is disabled" do + before do + saml_options[:slo_enabled] = false + post "/auth/saml/spslo" + end + + it "should return not implemented" do + expect(last_response.status).to eq 501 + expect(last_response.body).to eq "Not Implemented" + end + end end describe 'POST /auth/saml/metadata' do