Skip to content

Supporting multiple authentication strategies

Raphael Nestler edited this page Jul 7, 2022 · 6 revisions

You can support multiple, optional authentication strategies (including database_authenticatable) by namespacing routes and tracking how each user logged in.

Make sure you're aware of #22 when using database authentication.

Configuration

Use the saml_route_helper_prefix config option in config/initializers/devise.rb to prefix SAML routes.

Devise.setup do |config|
  config.saml_route_helper_prefix = 'saml'
end

Routes

Draw routes normally.

devise_for :users

Controller

Patch this gem's Devise::SamlSessionsController to add an after_action to store the warden winning_strategy so you know SAML was used to log in for this user.

Devise::SamlSessionsController.class_eval do
  after_action :store_winning_strategy, only: :create

  private

  def store_winning_strategy
    warden.session(:user)[:strategy] = warden.winning_strategies[:user].class.name.demodulize.underscore.to_sym
  end
end

Logout

Your logout button should use a custom action that uses the default sign_out to sign out regardless of scope; then redirects to destroy_saml_user_session_path if the winning strategy was SAML so that the user is signed out of the IdP.

class AuthController
  def sign_out
    saml_sign_out = authenticated_with_saml?
    sign_out
    if saml_sign_out
      redirect_to destroy_saml_user_session_path
    else
      redirect_to root_path
    end
  end

  private

  def authenticated_with_saml?
    warden.session(:user)[:strategy] == :saml_authenticatable
  rescue Warden::NotAuthenticated
    false
  end
end