Sign in as Another User Using Devise Token Auth in Rails Api Application

Guide on how to sign in as another user if you are admin using devise token auth in rails API application

Sanketkumar Karve

3 minute read

In normal Rails application, Sign in as another user if you are an admin comes in very handy when using devise and active admin. But was unable to find any content for Rails API app using devise token auth gem. As suggest by devise token auth, it uses devise gem for authentication so I looked into devise token auth gem for bypass_sign_in method.

1. Create Rails API application

Let’s create Rails API application using PostgreSQL database.

rails new demo-app --api --database=postgresql

and cd into rails app

cd demo-app

Configure database.yml file by adding host, username and password below pool line.

host: localhost
username: postgresql
password: <%= ENV['DEMO_APP_PASSWORD']%>

Now set up the database by using the command

rake db:create db:migrate

Your rails application is set up and you can run the server rails s

2. Installing Devise Token Auth Gem

Devise Token Auth gem is Simple, multi-client and secure token-based authentication for Rails.

Add the following to your Gemfile:

gem 'devise_token_auth'

Then install the gem using bundle:

bundle install

3. Generate User model

rails g devise_token_auth:install User auth

Above command will create a user model, define routes and include concerns.
It will also create config/initializers/devise_token_auth.rb file

Now run the migration.

rake db:migrate

In config/initializers/devise_token_auth.rb file check if config.change_headers_on_each_request is false. By default it’s false but incase of existing app check it.

Add bellow line in the config/initializers/devise_token_auth.rb file

config.bypass_sign_in = true

4. Create method login_as_user

Create new users_controller.rb file. You can create in:

app
  |-controller
      |-api
        |-v1
          |-users_controller.rb

Add following code in users_controller.rb file

module Api::V1
  class UsersController < ApplicationController
    before_action :authenticate_user!
  
    def login_as_user
      if (user_signed_in? && current_user.role === 'admin')
        DeviseTokenAuth.bypass_sign_in = true
        user = User.find_by_uid(params[:uid])
        current_user = user
        render json: current_user.create_new_auth_token, status: 200
      else
        render json: {message: "Invalid user."}, status: 400
      end
    end
  end
end

Here we are validating if the current user is signed in and role is an admin. Then we are searching for the user whom we have to log in as and set it as the current user. Then we call create new authentication token for the new user and pass details as a response.

Add the following in your routes file:

namespace :api do
  namespace :v1 do
    post 'users/login_as_user' => 'users#login_as_user'
  end
end

In response to API you will get the following details:

{
  access-token: "yBEgPr_i9zP_Nn8aXNPf2Q",
  client: "Ri9IsYu8Xg2c9ChHo6Czzw",
  expiry: "1538933563",
  token-type: "Bearer",
  uid: "test@example.com"
}

You can log in with the new token.

5. Tips on how to handle in the frontend

  • When you log in as admin you save your access-token, client and uid as current_user in local storage.
  • Before calling login_as_user API, save the admin details as current_admin in local storage
  • On calling the API you can store that new user details in current_user in local storage.
  • Likewise, to switch back to admin you can the API again with admin uid and set admin as current_user

6. Few handy tips

  • If you are facing an issue of token expires quickly that you can increase the expiration time by adding config.token_lifespan = 2.weeks in config/initializers/devise_token_auth.rb file.
comments powered by Disqus