Initial setup to get devise and devise_token_auth working in your Rails API

Jonathan Luk
4 min readOct 2, 2020

Greetings, fellow coders. Up to this point, every time I start building a new app, I usually(always) stumble around when it comes to setting up the authentication part. Since I’m building a new app now and authentication is what I tend to work on first, let me guide you through my process of setting up the authentication on my Rails API with devise and devise_token_auth.

First thing, let’s create your Rails app with the command:

rails new app_name — api

If you’ve already created an app without the — api flag, you can change it to an API app by following these directions: https://guides.rubyonrails.org/api_app.html#changing-an-existing-application

If and only if you decide to go with the full blown Rails application instead of just the API, you can add the following to your ApplicationController to avoid getting errors from failiing CSRF validation:

protect_from_forgery unless: -> { request.format.json? }

In a nutshell, Rails places a hidden tag with a CSRF token into it’s view forms, and on submission, it checks the CSRF token to make sure the browser used to submit the form is the same one that the form was displayed to. Since we’re not using the views, we won’t get a CSRF token, so we won’t need this. Creating the Rails app with the — api flag automatically removes this so we won’t have to add the above line.

Next step, install devise and devise_token_auth by adding them to your gemfile and running bundle install:

gem ‘devise’

Run command:

rails generate devise:install

Add to your config/environments/development.rb

config.action_mailer.default_url_options = { host: ‘localhost’, port: 3000 }

Install devise_token_auth:

gem ‘devise_token_auth’

Run command:

rails g devise_token_auth:install

Now let’s set up rack-cors to allow our new app to accept requests. More thorough information can be found here. https://github.com/cyu/rack-cors

Add gem ‘rack-cors’ to your gemfile and run bundle install.

Open up your application.rb and configure your CORS rules, make sure to expose ‘access-token’, ‘expiry’, ‘token-type’, ‘uid’, and ‘client’, which will be returned in the headers by devise_token_auth and used for authentication. Here’s an example of what it should look like:

DO NOT do it this way in production. You should specify the domain that your frontend will be sending requests from. I only have it this way for simplicity and will change it after I verify everything is hooked up properly and my Rails api is receiving requests.

Generate User class and nest under /auth in routes @ https://devise-token-auth.gitbook.io/devise-token-auth/config :

rails g devise_token_auth:install User auth

Update the routes.rb @ https://devise-token-auth.gitbook.io/devise-token-auth/usage/routes

mount_devise_token_auth_for ‘User’, at: ‘auth’

Update ApplicationController to include:

include DeviseTokenAuth::Concerns::SetUserByToken

I like to generate custom controllers in case I want to change anything. For now, I’d like to change the fields for my User class:

rails generate devise:controllers users

I removed :name, :nickname from the migration file and replaced it with :first_name, :last_name, and :username. I removed :image also, because I’ll be using ActiveStorage to attach the user avatar image to the model instead.

## User Info
t.string :first_name
t.string :last_name
t.string :username
t.string :email

The strong parameters have to be adjusted to permit these fields as well, add new fields into devise_parameter_sanitizer.
Update the ApplicationController so it now looks like this.

application_controller.rb

More information @ https://github.com/heartcombo/devise#configuring-controllers

Add the Trackable features back into the migration file or you will get the “NoMethodError: undefined method `current_sign_in_at’…” error.
More info @ https://stackoverflow.com/questions/55735895/nomethoderror-undefined-method-current-sign-in-at-for-user0x000055ce01dcf0a:

## Trackable
t.integer :sign_in_count, default: 0, null: false
t.datetime :current_sign_in_at
t.datetime :last_sign_in_at
t.inet :current_sign_in_ip
t.inet :last_sign_in_ip

Now we can migrate the database with:

rails db:migrate

If not already, you may be asked to set the environment for the migration:

rails db:migrate RAILS_ENV=development

If you’re getting the error “Missing ‘confirm_success_url’ parameter…” and if you plan to the :confirmable feature which seems to be enabled by default to send a confirmation email and redirect the user, you need to set the confirm_success_url in the config/initializers/devise_token_auth.rb by adding this line and replacing it with your desired url:

config.default_confirm_success_url = “https://localhost:3000"

More info on this error @ https://github.com/kylecorbelli/redux-token-auth/issues/24

That’s pretty much it, you can now launch Postman and try signing up Users by sending a POST request to http://localhost:3000/auth/
note: devise_token_auth doesn’t use the registrations#new route given by Devise, claiming that it will require significant modification in order to remove it.

Sign the user in:

Signing the user out requires that you pass the access-token, client and uid as params from the response header received from the signing in:

And that’s it, the most basic setup for devise and devise_token_auth. From here you can add or strip the features you do and do not need. Enjoy!

--

--