Rails 5 API + JWT setup in minutes (using Devise)

Rails 5 is a great choice for your new API application. It has build-in api mode that has everything you need without the unnecessary “full stack” stuff. In this article I will show you how to setup your new Rails 5 API app with JWT (JSON Web Token) authentication.

Step 1 — Rails in api mode

Assuming you have Ruby and RubyGems already installed (if not, I recommend great step-by-step guide on http://installrails.com/) just create new Rails project using new api option:

$ rails new my_api --api

With Rails 5 it is that simple! I won’t get into details how it really works. Just trust me that it’s a perfectly suited for your API-only application. You can read more about it in Rails guides.

Step 2— JWT authentication

JSON Web Token is a great solution for user authentication. It‘s a well documented standard that has many implementation across almost all popular programming languages including Ruby.

Image for post
Image for post

We will use devise-jwt gem which is a “is a devise extension that uses JWT tokens for user authentication.”. Great job done by the author let us use JWT with the well known Rails authentication engine. When I was first implementing JWT in my application I was wondering whether devise, which is designed to use in full-stack Rails apps, is a good choice for API-only mode, but I gave it a go and after a few small tweaks it works and does the job.

Let’s see how to integrate it! Start with adding gem to your Gemfile (remember to checkout for the newest available version and specify it in Gemfile):

gem 'devise-jwt'

Then we need to install devise as usual. If you not familiar with that gem or don’t remember how to do it checkout these instructions. Basically what you need for now is to run the devise:install script and generate a User model. I recommend reviewing migration file that devise’s model generator creates and make sure you will get only fields you need.

Assuming you have you User model ready it’s time to provide some JWT specific configuration. We need to enable the extension in the model and it should look like this:

Now we need to setup JWT Revocation Strategies. It’s an advanced topic and if you are interesting I highly recommend reading this article by the author of the gem. All you need is to create blacklist model and migration:

Last part is to place JWT configuration in config/initializers/devise.rb

As you can see here we will have /login and /logout endpoints. You need to generate secret key yourself by running rake secret and place it in your environmental variables (dotenv gem makes it super easy). I also set the token expiration time to 1 day, cos the default time too short (few minutes).

While we are here let’s tell devise we will not use navigational formats by adding the following line to the same file:

config.navigational_formats = []

It will prevent devise from using flash messages which are not present in Rails api mode.

Step 3 — Login/logout endpoints

If you don’t need to do extra stuff on login/logout you even don’t have to override default Devise controller actions. All we need to do is to tell devise to speak with us using json format. This is the simplest solution I found:

After you place that file in app/controllers we need to set routes:

As you can see we configure custom paths for our endpoints. If you are ok with default Devise paths ( users/sign_in , users/sign_out , users/sing_up ) just remove path and patch_names keys.

Step 4— Registration

For sign-up endpoint we will override Devise controller action with

The main reason for that is that on registration you usually do things like sending emails or tracking, so sooner or later you will have to write you own action. You may notice that we use a render_resource method which is not part of Devise API. It’s a custom method that I use for rendering resources (it’s not only for User resource). You can place it in app/controllers/application_controller.rb

Step 5— Request Specs

Specs are the easiest way to make sure your API works as expected. In real world it’s better to write specs first, but for the blog post we will finish with that.

We will write some request specs. Why not controller specs? Because they don’t test the whole stack. They only create an instance of the controller class and fire the action method. They are useful if you have legacy code and want to refactor fat controllers. Otherwise I recommend using request specs which makes actual request and you test only the output (and critical side effects if needed). Using request spec also allows you to use Watchdocs which can generate your API documentation and helps you keep it up-to-date.

I will provide you with example specs in RSpec, just to give you an idea how those specs could look like.

First spec is for authentication endpoints and in addition for response status it also tests for JWT token presence and validity.

The second spec is for registration endpoint:

Step 6— Build your app

Now when you have authentication you can start building your API. In every controller that should be available only for authenticated users use a standard Devise’s

before_action :authenticate_user!

and you are at home!

Conclusion

I’ve just shown you how to start with Rails 5 in API mode and how to configure it to work with JWT using our best friend — Devise. This is of course a basic configuration, but it will work for most of the cases. For further reading on topics I mentioned here I recommend:

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store