Simple authentication for rails.
Installation
gem 'auth_rails'
CLI
- init
auth_rails
rails g auth_rails
- init
auth_rails
with strategy
rails g auth_rails --strategy allowed_token
- create migration for
allowed_token
strategy
rails g auth_rails:migration --strategy allowed_token
- if your model is not User
rails g auth_rails:migration --strategy allowed_token --model CustomUser
Configuration
- User model must have
has_secure_password
# app/models/user.rb
class User < ApplicationRecord
has_secure_password
end
# config/initializers/auth_rails.rb
AuthRails.configure do |config|
config.jwt do |jwt|
jwt.strategy = AuthRails::Strategies::AllowedTokenStrategy # default is AuthRails::Strategies::BaseStrategy
jwt.access_token do |access_token|
access_token.exp = 1.hour.since # optional
access_token.algorithm = 'HS256' # optional, default is HS256
access_token.secret_key = ENV.fetch('JWT_SECRET', 'secret_key') # optional
end
jwt.refresh_token do |refresh_token|
refresh_token.http_only = true # optional
refresh_token.exp = 1.year.since # optional
refresh_token.algorithm = 'HS256' # optional, must provide if project supports refresh token
refresh_token.cookie_key = :project_ref_tok # optional
refresh_token.secret_key = ENV.fetch('JWT_SECRET', 'secret_key') # optional
end
end
end
Rails.application.config.to_prepare do
AuthRails.configure do |config|
config.resource_class = User # required
config.error_class = ProjectError # optional
end
end
Usage
# config/routes.rb
Rails.application.routes.draw do
namespace :api do
resource :auth, path: 'auth', controller: 'auth', only: %i[create] do
collection do
get :refresh
end
end
end
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::API
# to include helpers for authenticating using access_token
include AuthRails::Authentication
# this action will assign user to CurrentAuth.user if valid token
# else raise error: AuthRails::Error or custom error in configuration
before_action :authenticate_user!
end
# app/controllers/api/auth_controller.rb
module Api
class AuthController < AuthRails::Api::AuthController
end
end
- If you want to support refresh token
# app/models/user.rb
class User < ApplicationRecord
include AuthRails::Concerns::AllowedTokenStrategy
has_secure_password
end
Customize
- Custom Strategy
class CustomStrategy < AuthRails::Strategies::BaseStrategy
class << self
# this is for getting user/resource using payload from access_token
def retrieve_resource(payload:)
super
end
# this is for generating refresh token
# if you do not support refresh token, can ignore this one
def gen_token(resource:, payload:, exp: nil, secret_key: nil, algorithm: nil)
super
end
end
end
- Custom response for controller
module Api
class AuthController < AuthRails::Api::AuthController
private
def respond_to_create(data)
render json: {
profile: CurrentAuth.user,
tokens: {
auth_token: data[:access_token],
refresh_token: data[:refresh_token]
}
}
end
end
end
- In case your identifier is not email
Rails.application.config.to_prepare do
AuthRails.configure do |config|
config.resource_class = User # required
config.identifier_name = :username # must be string or symbol, default is email
end
end
- If you have a custom method to validate password
Rails.application.config.to_prepare do
AuthRails.configure do |config|
config.resource_class = User # required
config.identifier_name = :username # must be string or symbol, default is email
config.authenticate = ->(resource, password) { resource.password == password } # must be a proc, validate password
end
end
- Sometimes, you have a complex logic to get the user
Rails.application.config.to_prepare do
AuthRails.configure do |config|
config.resource_class = User # required
config.identifier_name = :username # this one is sub in jwt
config.dig_params = ->(params) { params[:identifier] } # must be a proc, how to get identifier from params
# how to get user from identifier
# identifier default is params[<identifier_name>]
# or extract from dig_params
config.retrieve_resource = lambda { |identifier|
User.where(email: identifier)
.or(User.where(username: identifier))
.first
}
end
end
Strategy list
- allowed_token
License
The gem is available as open source under the terms of the MIT License.