waiting-for-dev / devise-jwt

JWT token authentication with devise and rails
MIT License
1.25k stars 129 forks source link

current_user nil after authentication #259

Closed Amystherdam closed 1 year ago

Amystherdam commented 1 year ago

Expected behavior

That the current_user is filled with the logged in user

Actual behavior

When the user logs in and the request is going through one of Devise's default controllers, the current_user is populated, but when the user is already logged in, the current_user is lost and becomes null

Even in application_controller current_user is already null

Settings made

config/initializers/devise_jwt.rb

# https://github.com/waiting-for-dev/devise-jwt/pull/23
# https://github.com/plataformatec/devise/issues/4584

module Devise
  module JWT
    module WardenStrategy
      def authenticate!
        super
        env["devise.skip_trackable".freeze] = true if valid?
      end
    end
  end
end

Warden::JWTAuth::Strategy.prepend Devise::JWT::WardenStrategy

config/initializers/devise.rb

  config.jwt do |jwt|
    jwt.secret = "testtesttesttest"
    jwt.request_formats = { user: [:json] }
    jwt.expiration_time = 30.minutes.to_i
    jwt.dispatch_requests = [
      ['POST', %r{^/users/sign_in.json$}]
    ]
    jwt.revocation_requests = [
      ['DELETE', %r{^/users/sign_out.json$}]
    ]
  end

app/models/user.rb

class User < ApplicationRecord
  include Devise::JWT::RevocationStrategies::JTIMatcher

  devise :database_authenticatable, :registerable, :validatable,
         :jwt_authenticatable, jwt_revocation_strategy: self
end

JTI Migration

class AddJtiToUsers < ActiveRecord::Migration[7.0]
  def change
    add_column :users, :jti, :string, null: false
    add_index :users, :jti, unique: true
  end
end

Debugging information

Provide following information. Please, format pasted output as code. Feel free to remove the secret key value.

Amystherdam commented 1 year ago

Putting this in application_controller or graphql_controller if using graphql should work, assuming your GraphqlApiService file or whatever frontend file is sending the bearer token in the header of each request

  def current_user
    return unless request.headers['Authorization'].present?
    token = request.headers['Authorization'].split(" ").last
    warden.authenticate!(auth_token: token)
  end