JwtSecure is a small gem that helps you use jwt authentication in rails app using http only cookies
Check this demo api built using jwt-secure
Require jwt_scure in config/routes.rb file and add routes for login and logout acording to your needs. note (you don't need to create any namespace you can also define routes without namespace, since most people will be building apis so I created a api namespace in the demo app.)
path: config/routes.rb
require 'jwt_secure'
Rails.application.routes.draw do
namespace :api do
post "/login", to: "auth#login"
get "/logout", to: "auth#logout"
get "/test", to: "test#some"
end
end
Avobe the route /test is protected by default when we create class Api::TestController < ApiController
and you have to make sure your ApiController inherit from JwtSecure::ApiJwtController
Create a base controller like ApiController < JwtSecure::ApiJwtController
that you will be inheriting in all your api controllers or controllers that needs to be protected / using jwt auth (like only give access if logged in typeof controllers)
path: app/controllers/api_controller.rb
class ApiController < JwtSecure::ApiJwtController
def authenticate_jwtsecure
@jwtsecure_cookiename = :mysite_token
@jwtsecure_secret = "some_key_string_secret"
super
end
end
make sure you have defined the authenticate_jwtsecure method and made two instance variable for cookiename and jwt secret key. Http only cookies will be saved acording to @jwtsecure_cookiename
variable value
@jwtsecure_cookiename = :any_cookie_name
@jwtsecure_secret = "some_strong_secret_key"
Create the controller for login and logout route you can name the controller anything you want for this demo app I used the name auth_controller.rb
path: app/controller/api/auth_controller.rb
class Api::AuthController < JwtSecure::AuthController
skip_before_action :verify_authenticity_token
def login
@jwtsecure_usermodel = User
@jwtsecure_findby = { username: params[:username] }
@jwtsecure_password = params[:password]
@jwtsecure_cookiename = :mysite_token
@jwtsecure_secret = "some_key_string_secret"
super
end
def logout
@jwtsecure_cookiename = :mysite_token
super
end
end
Make sure to profile the user model in @jwtsecure_usermodel
instance variable.
@jwtsecure_findby
should be the query that you want to find the user and check his password. For example if you want to find the user by his email and check password you should put @jwtsecure_findby = { email: params[:email] }
or anything that you want acording to your user model.
@jwtsecure_password
should be the password that is coming from params from the request at /api/login
or acording to your routes.
If user is found and password is correct then you will get a response back with a message and the user info. note(make sure to put same cookiename and jwtsecret for all the instance variable or it won't work)
Your secure jwt auth is now complete now anything that you want to protect with jwt auth you can make controller for that and it must inherit from the base controller that is inheriting from JwtSecure::ApiJwtController
. In my example I am using ApiController < JwtSecure::ApiJwtController
so I will use Api::TestController < ApiController
.
path: app/controllers/test_controller.rb
class Api::TestController < ApiController
def some
puts @current_user
puts @current_user.username
render json: {some: "shit", current_user: @current_user.username}
end
end
@current_user the the user object recieved from the database. you can access user name or email if present or any other information in every controller that is inheriting from the BaseController in this case it's ApiController.
for loging out / clearing the cookie just make a route and point it to your auth controller logout action. Your auth controller should inherit from JwtSecure::AuthController
and must have login
and logout
methods with all required instance variables.
if you want some routes to not have auth and can be accessed by anytone you can bypass auth check for that controller using skip_before_action :authenticate_jwtsecure
Bellow is example of the test route without auth checks
path: app/controllers/test_controller.rb
class Api::TestController < ApiController
skip_before_action :authenticate_jwtsecure
def some
puts @current_user #-> will result in error since there is no user cuz route is a open route
puts @current_user.username #-> will result in error
render json: {some: "shit"}
end
end
This will automaticly set a http only cookie in your cookies in browser or any client you use like postman. And at any route that has a controller that's inheriting from ApiController
or whatever name you have for the base controller that request will be automaticly checked for a http only cookie and if that cookie is valid, if valid then it will put the user object retrived from model to @current_user
instance that can be used anywhere in the controller, else it will give a response back saying invalid token if http cookie not present or it's wrong.
Contributions, issues, and feature requests are welcome!
Feel free to check the issues page.
If you like this project please give a star.
I would like to thank all the people that contributed in this project .