This article is all about authentication in rails 6 using devise and devise-jwt with fast_jsonapi response.
A lightning fast JSON:API serializer for Ruby Objects. It is better in performance compared to Active Model Serializer.
Devise-jwt is a devise extension which uses JSON Web Tokens(JWT) for user authentication. With JSON Web Tokens (JWT), rather than using a cookie, a token is added to the request headers themselves (rather than stored/retrieved as a cookie). This isn’t performed automatically by the browser (as with cookies), but typically will be handled by a front-end framework as part of an AJAX call.
In this step, We need to create a rails application with api_only mode with optional database params(If you want to change).
$ rails new test-app –api –database=postgresql
Here, I have created a rails 6 application using postgresql (Default SQLite).
(Note: If you are using postgresql then you have to setup database.yml)
As this is an API Only application, we have to handle ajax requests. So for that, we have to Rack Middleware for handling Cross-Origin Resource Sharing (CORS)
To do that, Just uncomment the “gem ‘rack-cors’” line from your generated Gemfile. And add the following lines to application.rb.
Here, we can see that there should be an “Authorization” header exposed which will be used to dispatch and receive JWT tokens in Auth headers.
Here, we are going to add gem like ‘devise’ and ‘devise-jwt’ for authentication and the dispatch and revocation of JWT tokens and ‘fast_jsonapi’ gem for json response.
Then, do ‘bundle install’
By running the following command to run a generator
$ rails generate devise:install
It is important to set our navigational formats to empty in the generated devise.rb by adding the following line since it’s an api only app.
Also, add the following line to config/environments/development.rb
You can create a devise model to represent a user. It can be named as anything. So, I’m gonna be going ahead with User. Run the following command to create User model.
$ rails generate devise User
Then run migrations using,
$ rake db:setup
$ rake db:create
$ rake db:migrate
We need to create two controllers (sessions, registrations) to handle sign ups and sign ins. By,
rails g devise:controllers users -c sessions registrations
specify that they will be responding to JSON requests. The files will looks like,
Then, add the routes aliases to override default routes provided by devise in the routes.rb
Create a rake secret by running the following command.
$ bundle exec rake secret
Add the following lines to devise.rb
Here, we are just specifying that on every post request to login call, append JWT token to Authorization header as “Bearer” + token when there’s a successful response sent back and on a delete call to logout endpoint, the token should be revoked.
The jwt.expiration_time sets the expiration time for the generated token. In this example, it’s 30 minutes.
Revocation of token is conflicting with the main purpose of JWT token. Still devise-jwt comes with three revocation strategies out of the box. Some of them are implementations of what is discussed in the blog post JWT Revocation Strategies
Here, for the revocation of tokens, we will be using one of the 3 strategies.
Create a jwt_blacklist model by the following command
$ rails g model jwt_blacklist jti:string:index exp:datetime
Add these two lines to the “jwt_blacklist.rb”
Add these two options to your devise User model to specify that the model will be jwt authenticatable and will be using the blacklist model we just created for revocation.
:jwt_authenticatable, jwt_revocation_strategy: JwtBlacklist
The final user model will look like this
Now run migrations using “rails db:migrate”
As we already added a fast_jsonapi gem. For json response for user data, we have to create a user serializer. By following command,
$ rails generate serializer user
It will create a serializer with predefined structure.Now, we have to add the attributes which we have to set as a user response. So I have added user’s id, email and created_at.So the final version of user_serializer.rb
We can access serializer data for single record by,
And multiple records by,
Now, we have to tell devise to communicate through JSON by adding these methods in the RegistrationsController and SessionsController
You can modify the column name and data format by overwrite attribute:
attribute :created_date do |user|
Here, I have changed created_at attribute’s column name and its format.
Here you can get detailed information on fast_jsonapi.
Now you can add the following line in any controller to authenticate your user.
If you are looking to develop any project on Ruby on Rails then choose us as we are one of the leading Ruby on Rails Development Company that provides quality Ruby on Rails development services. Contact us to hire Ruby on Rails developers for your Ruby on Rails requirement or you can reach us at firstname.lastname@example.org