Ever wondered how to login as another user within Devise?
Recently we had a feature request that would provide Admins with the ability
to sign is as another user. You could imagine live demonstrations or even production
support calls where you would like to be signed in as another user, yet not
have to ask for or decrypt their current password. After stewing for a bit, we found a
pretty nice solution with Devise.
Here’s the Cucumber feature…
Feature: Sign in as another user
As an admin
I want to sign in as another user
Scenario: Admin can sign in as another user
Given I am logged in as an admin user
And a user: "bob" exists with email: "email@example.com", password: "password", ...
When I go to the admin users page
And I follow the "Sign in as" link for user: "bob"
Then I should see "Welcome Bob"
The trick was to store the admin info within the rack session.
We decided on using a Rails 3 concern to keep our actual strategy clean.
request.env['rack.session']['devise.remember_admin_user_id'] = id
request.env['rack.session'] && request.env['rack.session']['devise.remember_admin_user_id'].present?
request.env['rack.session']['devise.remember_admin_user_id'] = nil
The above really makes writing the Devise strategy fairly easy.
class FromAdmin < ::Devise::Strategies::Base
resource = User.find(remember_admin_id)
Then we just wire in our new strategy. Last line above.
Lastly, here’s our sign-in-as controller which sets the Devise session variable.
class SignInAsController < ApplicationController
if can?(:manage, :users)
self.remember_admin_id = current_user.id
sign_in :user, User.find(params[:user_id])
That’s it, pretty neat and might make for a nice Gem or Devise addition.