How to Use JWT Authentication in a Rails 5 API App

Feature thumb snip20170830 46

A standard requirement for API only applications is to have an authentication mechanism. A use case would be if you have a JavaScript front end (aka Angular, React, Vue, etc), and a Ruby on Rails API backend. I'll include a link in the resource section if you want to know more about JWT token authentication. Currently, my favorite RubyGem to integrate this type of functionality is the Knock Gem. And in this guide, I'll walk through how to integrate Knock so your API Rails apps can use JWT token authentication.

 

Step 1 - Build a User Model

For API only applications I typically prefer to build a minimal authentication system instead of using a heavier library, such as Devise. It's possible to use Devise with JWT tokens, but it's not my favorite implementation.

If you are going to follow along, you will want to start with a blank application, you can generate the application with the following commands:

rails new jwt_token_app --api --database=postgresql -T

Change into the application and build the database:

rails db:create && rails db:migrate

Now we can generate the User model with an email and password digest (we're going to use the Bcrypt gem that will encrypt this password field, and using the password_digest name is the naming convention to follow).

rails g model User email:string password_digest:string

That will build the model and migration file. Now run the migration:

rails db:migrate

Now let's add the Bcrypt gem to the Gemfile:

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

Then run bundle install. And in order to encrypt the password_digest field, update the app/models/user.rb file so it looks like this:

You can test this out by starting up the rails console and testing out the user creation process:

> User.create!(email: 'jon@snow.com', password: 'asdfasdf')

This should create the user and if you run the User.last query you should see a new user has been added to the database with an encrypted password, such as the output below:

 

Step 2 - Integrate Knock

With our User model created we can now start integrating the Knock gem to manage the JWT management process. Start off by adding the Gem to your Gemfile and running bundle install:

gem 'knock', '~> 2.1', '>= 2.1.1'

(As a shortcut, you can run: echo gem '"knock', '~> 2.1', '>= 2.1.1'" >> Gemfile in the terminal to append a line of code to the end of the file)

Next, let's include Knock's helper module in the application controller:

Now create the controller with the Knock controller generator:

rails generate knock:token_controller user

This will build a controller that inherits from the Knock controller. Additionally, it will draw a route so that we can call the API endpoint.

Now let's run the Knock generator to build the initializer file:

rails generate knock:install

That will build an initializer file with a ton of comments that you can customize to fit your own needs:

Step 3 - Test it Out

With all of this in place, we should be able to login in via an API call. Start by running the rails server:

rails s

And then open up a new terminal tab and run this command (replace the email and password with the credentials you gave when you created the user in the console).

curl -X POST "http://localhost:3000/user_token" -d '{"auth": {"email": "jon@snow.com", "password": "asdfasdf"}}' -H "Content-Type: application/json"

If everything works you should receive a bright and shiny new JWT token back as a response:

{"jwt":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJleHAiOjE1MDQyMjUxNDQsInN1YiI6MX0.KTNcakZujrQ2nG1pjb2y1lP_OZ5K4rPIS4IBr3Ac2Eg"}

Now if you try to login via the API with user credentials that aren't valid, you should receive no response back:

curl -X POST "http://localhost:3000/user_token" -d '{"auth": {"email": "nope@noper.com", "password": "asdfasdf"}}' -H "Content-Type: application/json"

And that's it! You now have the ability to authorize users via JWT with any 3rd party applications. Nice work! Below I've included a link to the source code for the sample application as well as the introductory guide to JWT and the Knock Gem documentation.