Authenticating Rails Web Services With JWT

 

This blog will help you to set up simple JWT authentication solution for your Rails API. However, i have implemented many authentication solutions in our projects, but i personally felt that JWT is best and secured web token and that provides an easy way to handle the information shared between the client and server. On this blog, let’s see how we can implement JWT for authentication and to transfer information between resources.

 

What Is JWT?

 

JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for creating access tokens.

JWT consists of three parts and its basically separated by dots,

  • Header
  • Payload
  • Signature

Header – Header is the first part of the JWT token, It consists of two things, One is the type of algorithm used to generate signature and second is the type of token.

Payload – Payload is the second part of the JWT token. It consists of information about the entity.

Signature – Payload is the third part of the JWT token, It is calculated by base64url encoding the header and payload.

 

How to implement JWT in Rails application?

 

Step: 1 – First create a new rails application

rails new app

Step: 2 – Add the jwt gem into Gemfile.

 

gem 'jwt'

 

Also Read: Caching In Ruby On Rails 5.2

 

Step: 3 – Create JWT service file

 

Create JsonWebToken class under lib/json_web_token.rb file. This will be used to create and validate the jwt token.

JsonWebToken’s encode method is used to create JWT token by using payload and secret key.

JsonWebToken’s decode method is used to decode the token to convert payload using secret key.

 

class JsonWebToken
def self.encode(payload)
JWT.encode(payload, ENV["SECRET_KEY_BASE"])
end
def self.decode(token)
return HashWithIndifferentAccess.new(JWT.decode(token, ENV["SECRET_KEY_BASE"])[0])
rescue
nil
end
end

 

Step: 3 – Create users and jwt_tokens table.

 

Here the below tables used to handle user and session tokens.

users – Used to store user details and login information.

 

create_table "users" do |t|
t.string "first_name"
t.string "email", default: "", null: false
t.string "encrypted_password", default: "", null: false
t.string "api_key", null: false
end

 

Jwt_tokens – Used to store the sessions details and jwt tokens.

 

create_table "jwt_tokens" do |t|
t.bigint "user_id"
t.string "token"
end

 

Related: 10 Useful Ruby On Rails Gems We Couldn’t Live Without

 

Step: 4 – Create a rails model for above tables

 

1. Add User under app/models/user.rb

 

Each users will have unique API_KEY, also each user will have many jwt tokens. Usually, these JWT tokens are stored in jwt_tokens table.

 

 

class User < ApplicationRecord
# Validations
validates :first_name, :last_name, :email, presence: true
validates :email, uniqueness: true
# associations
has_many :jwt_tokens
def assign_api_key
self.api_key = SecureRandom.uuid
end
end

 

2. Add JwtToken under app/models/jwt_token.rb

 

class JwtToken < ApplicationRecord
belongs_to :user
end

 

Step: 5 – Create sessions API to create JWT

 

In sessions, API validates the user authentication, and it will create the jwt token using JsonWebToken class. JWT token will be stored in a jwt_tokens table along with api_key. These tokens will be used to verify the further requests.

 

# sessions controller
require 'json_web_token'
class SessionsController < Devise::SessionsController
def create	
user = User.find_for_database_authentication(email: params[:user][:email])
if user && user.valid_password?(params[:user][:password])
render json: payload(user, params)
else
render json: {success: false, message: 'Invalid details' }, status: :unauthorized
end
end
private
def payload(user, params = {})
jwt_token = user.jwt_tokens.create(token: SecureRandom.uuid)
{
api_key: user.api_key,
auth_token: JsonWebToken.encode({token: jwt_token.token})
}
end
end

 

 

Step: 6 – Create User details API to use JWT token as a session token

 

In user details API the jwt token is passed through headers, and the tokens are decoded using JsonWebToken class. The decoded token is validated against the stored token and this is how the session will be maintained between client and server.

 

# users controller
require 'json_web_token'
class UsersController < Devise::SessionsController
# validate the session using JWT token
before_action :authenticate_request!
def show
render json: { success: true, user: @user }
end
def authenticate_request!
token = JsonWebToken.decode(request.headers['Authorization'])
@user = User.joins(:jwt_tokens).where('jwt_tokens.token =?', token).last
render json: { error: 'You are not authorized' }, status: :401 unless token || @user
end
end

 

So far i have covered the process of creating sessions using JWT and also the procedure of handling sessions. Hopefully you can use JWT for creating secured tokens to protect your web services.

Hope this helps you! Similarly you can learn more on interesting on latest technologies, never miss out anything from  our largest blog portal where you can get continuous blog updates & latest posts about all the latest technologies which would be perfect for your 15 minutes tea break! In case if you’re a newbie then don’t forget to subscribe us to get the latest updates from diverse technologies. What else guys hit the  subscribe link  and go crazy over learning.

 

For more inquires reach us via info@agiratech.com