flonath
4/5/2013 - 1:47 PM

Unified sign in form for multiple types of Devise users.

Unified sign in form for multiple types of Devise users.

class SessionsController < Devise::SessionsController
  def create
    # try to authenticate as a User
    self.resource = warden.authenticate(auth_options)
    resource_name = self.resource_name

    if resource.nil?
      # try to authenticate as an AdminUser
      resource_name = :admin_user
      request.params[:admin_user] = params[:user]

      self.resource = warden.authenticate!(auth_options.merge(scope: :admin_user))
    end

    set_flash_message(:notice, :signed_in) if is_navigational_format?
    sign_in(resource_name, resource)
    respond_with resource, :location => after_sign_in_path_for(resource)
  end
end
MyApp::Application.routes.draw do
  devise_for :users, controllers: { sessions: 'sessions' }
  devise_for :admin_users, controllers: { sessions: 'sessions' }
end
# Monkey patch to remove memoization from Devise mapping lookup.
# We need to be able to switch between different mappings at runtime
# in order to authenticate different types of users.
module Devise
  module Strategies
    class Base
      def mapping
        # @mapping ||= begin
          mapping = Devise.mappings[scope]
          raise "Could not find mapping for #{scope}" unless mapping
          mapping
        # end
      end
    end
  end
end

An application I'm working on has two different types of Devise users, but I want both types of users to be able to use the same sign in form. Devise doesn't make this easy.

You could argue that I really should have a single user type with a role attribute, but the app is far enough along that I don't want to change that early design decision. It could be changed later if more pain points are discovered.

You could also argue that I shouldn't use Devise, but it's still the de facto authentication standard for Rails applications.

In this example, you can sign in as either a User or an AdminUser. This application only has two types of user, but this example could be extended to support any number of them more gracefully.