Recipe for Adding Authentication to a Rails API Only Application with an HTTP Only Cookie

Feature thumb authentication

It seems like the go-to authentication tool for developers connecting front end applications (React, Vue, Angular, etc) is to use JWT tokens. However there are a number of potential security vulnerabilities with that approach, and I've also discovered that it moves too much authentication/authorization logic to the client. Whereas this type of responsibility should reside on the server (in my humble opinion).

I'm not going to discuss the pros/cons of which tool to use in this guide, for more information I've included a link to a very helpful article that walks through the topic. The goal of this guide is to give a step by step tutorial for enabling a Rails API only application to utilize HTTP only cookies to manage auth.

This tutorial assumes that you're using:

Rails 5.2+ Ruby 2.5+


Step 1 - Install the bcrypt gem

gem 'bcrypt', '~> 3.1', '>= 3.1.12'


Step 2 - Build User Model

rails g model User email password_digest auth_token:text


Step 3 - Add has_secure_password to User Model

It should look something like this:


Step 4 - Create a Cookies Serializer Initializer

Create a file here: config/initializers/cookies_serializer.rb

And add the code:

Rails.application.config.action_dispatch.cookies_serializer = :json


Step 5 - Create Session Store Initializer

Create a file: config/initializers/session_store.rb

And add in code that defines the name of the cookie along with the domain that you're going to use it on, such as:

Rails.application.config.session_store :cookie_store, key: '_my_app_name_session', domain: ''


Step 6 - Create Authentication Routes

Update the config/routes.rb file to include these routes.


Step 7 - Build Token Concern

Create a concern file here: app/controllers/concerns/auth_token_concern.rb

And add the following code to it:


Step 8 - Built the Registration Controller


Step 9 - Test it!

You can run POST request from your own application, or from a front end app to confirm that it's working. (I'll build this into a future tutorial using a front end application)