Learn react on railsSort Order

Rails API: Devise and JWT Integration Part 2 - [041]

Now that we've got the devise custom strategy let's integrate it and make devise warden aware of it.

Integrating our Custom Strategy to Devise

We'll need to configure devise in config/devise.rb around line 256 look for code that looks like the following. Go ahead and uncomment it and add the following code.

config.warden do |manager|  manager.strategies.add(:jwt, Devise::Strategies::JWTAuthentication)    manager.default_strategies(scope: :user).unshift :jwtend

Now devise is aware of our custom strategy.

Cleaning up JWT Encode / Decode

We need a place that we can use to manage the encoding and decoding of the token. Let's start by creating a lib/web_token.rb

module WebToken  SECRET = Rails.application.secrets.secret_key_base  EXPIRY = (Time.now + 2.weeks).to_i  class << self    def decode(token)      JWT.decode(        token,         WebToken::SECRET,         true, { algorithm: 'HS256' }      ).first    rescue JWT::ExpiredSignature      :expired    end    def encode(user)      JWT.encode(        token_params(user),         WebToken::SECRET,         'HS256'      )    end        private        def token_params(user)      {        user_id: user.id,        exp: EXPIRY      }    end  endend

Once we implement this we also need to make sure that our Rails app autoloads the lib directory. In config/application.rb

module Invoiced  class Application < Rails::Application        # ...    config.autoload_paths << Rails.root.join('lib')        # ...  endend

Make sure you add lib to the autoload paths.

Cleaning up the Controllers

In our application_controller.rb we can remove most of the code leaving only the current_account method.

class ApplicationController < ActionController::API  def current_account    @current_account ||= Account.friendly.find(params[:account_id])  endend

In the SessionsController#create we can remove the token generation code and replace it with our new WebToken module.

def create  @user = User.where(email: params[:email]).first  if @user&.valid_password?(params[:password])    jwt = WebToken.encode(@user)    render :create, status: :created, locals: { token: jwt }  else    render json: { error: 'invalid_credentials' }, status: :unauthorized  endend

That's it! Now we can use all the utility methods of devise with JWT authentication.