DEV Community

Ali Zand
Ali Zand

Posted on

Setting Up User Auth With React and Rails Minus The JWT Headache

Problem

Most of the tutorials that I've encountered on setting up User Auth for React and Rails with Devise involves the following components:

  • Rails API
  • Devise
  • CORS setup for Rails
  • Some sort of JWT library like Doorkeeper or devise-jwt
  • Use of localStorage to store the JWT token.

The are multiple problems with the above setup. The most important of which is storage of the JWT token in localStorage. This is not a safe method as other JS would have access to localStorage and the JWT can be compromised.

The second problem with this method is how much work it takes to complete the setup.

Solution

Turns out a secure HTTP Cookie is the most secure method of storing the user session data on the frontend.

  • Rails (none-API)
  • Devise
  • nginx

Notes: I will not go over the initial Rails or Devise setup in this document as it is very well documented through Rails and Devise documentation.

The key to this solution working is the using the same domain for the frontend and the backend.

Repo Setup

React application and Rails application do not be in the same repo and React application does not be setup as part of the Rails application for this solution to work.

Steps

  • Setup Rails and Devise following steps from their respective documentation.
  • Setup puma to run on a different port than React either by updating config/puma.rb to include
port ENV.fetch("PORT") { 3001 }
Enter fullscreen mode Exit fullscreen mode

or using the -p option:

rails s -p 3001
Enter fullscreen mode Exit fullscreen mode

In my case I have chosen port 3001

  • Setup the React Application.
  • Setup nginx: We will use nginx as a proxy pass to redirect calls to / to the React frontend and the calls to /api to the Rails backend.
# /etc/nginx/sites-available/default
server {
    listen 80;
    listen [::]:80;

    server_name my.amazing.website.com;

    location / {
         proxy_pass http://127.0.0.1:3000;
    }

    location /api {
         proxy_pass http://127.0.0.1:3001;
    }
}
Enter fullscreen mode Exit fullscreen mode
  • Restart nginx to load the new configuration sudo service nginx reload
  • Place the users routes under the /api scope
  scope '/api' do
    devise_for :users
  end
Enter fullscreen mode Exit fullscreen mode
  • Enable rails to respond to json requests by adding the following to the ApplicationController
respond_to :json
Enter fullscreen mode Exit fullscreen mode
  • Allow Rails to accept post requests w/o providing an authenticity token by adding the following to the ApplicationController
skip_before_action :verify_authenticity_token
Enter fullscreen mode Exit fullscreen mode

Top comments (0)