I have been using Devise Token Auth gem for Rails API only projects.
There seems some issues with this gem:
- First, devise token auth is an extension of devise gem which has majority settings that devise token auth uses.
- Second is through gem we get great many settings of devise and devise token auth by which we need not use in day to day projects.
- Third due to usage of two gems parent and child, we need to know all the documentation of both gems to work appropriately with this.
- Furthermore, we don’t get much control over our authentication system that we build because of dependency of gems.
These issues led to build my authentication system that I code customise the code myself on day to day based on the project that I am working on.
This tutorial doesn’t intend to demonstrate another gem as I felt it would be better not to create a gem with settings. Rather I wanted to have the code and concept so that I can duplicate and change all the stuff according to the project.
What a good authentication system initial concepts involve for APIs?
- First there should be a user model on which we want to implement authentication. User should have at least email and hashed password for authentication.
- Second there should normally be a session of the user which can be used for request authentication. But as APIs are complete cut off with the browser page so only requests/responses are the connection with the server. So, when the response completes, session gets closed. So, we need to have some session token passed to the server which verifies the user and gives response. This is called Token-based Authentication System.
- There should be a way that a user can be logged in at the same time to multiple devices like phone, tablet, computer. So, we will need different sessions for the same user.
- User should be able to confirm his/her email and reset her/her password as well.
- Finally, User should be able to log in with OAuth, i.e., Google, Facebook ETC.
In this tutorial, We will look into all this concepts and makes our code fulfilling these concepts. The First time devs creating their code will think of this tutorial as against convention over configuration. But when you put these concepts to use in different projects, you will consider it to be great because you will be able to change/debug everything easily then.
I use the docker-compose system to initiating the api for rails. Tutorial is given here.
So, I am assuming that you have initialised the rails project.
Create user model by following command:
rails g model User name:string email:string:uniq password_digest:string email_confirmed_at:datetime:index
You may have noticed that we entered
password_digest not password. As we will be using bcrypt gem for hashing user passwords. Add this to gemfile and run
bundle install. Their documentation says just do below two things and all passwords will be hashed:
- Name the column for password storage as
- Add line
So, we will now have user model after above command, run migration and if you access the console and create a user, then you will see that
password_digest column has gibberish values.
Now create a session model. A user can have many sessions and a session belongs to a user. The Session model contains the last used timestamp so that we can check when was this session last used by the user. Status that tells if this session is active or not. A token column that saves a unique string to verify the session. Create a session model by calling:
rails g model Session user:references last_used_at:datetime:index status:boolean:index token:string:uniq
Now create a model that will work for user confirm email or user’s reset password. This model will have an extra
verify_type column that will contain options to have different verification systems for future.
rails g model UserVerification user:references status:string:index token:string:uniq verify_type:string:index
These are all the models we need for now to create our authentication system. In the next article we will work on controller designs for authentication.