waiting-for-dev/devise-jwt

Not able to retrieve user_id from another controller. Kindly request for your help

mariosknl opened this issue · 5 comments

Please, for a bug report fill in the following template. Before that, make sure to read the whole README and check if your issue is not related with CORS.

Feature requests and questions about devise-jwt are also accepted. It isn't the place for generic questions about using devise with an API. For that, read our wiki page or ask somewhere else like stackoverflow

Expected behavior

I am using devise & devise-jwt for my User Authentication System. I'm building a full-stack project using Rails for the API and React & Redux for the front-end. Also, I have set up my Rails API so each time a user signs in, I'm setting a cookie in the browser. Everything works perfectly for me up to this point. So, I also have another controller that I'm using for the like functionality. While executing methods in that controller trying to retrieve the user data stored in the same cookie I'm getting NIL JSON Web Token. The cookie is unreachable for some reason. Can you please help me out with that?

Actual behavior

I was expecting to get the user_id.

Steps to Reproduce the Problem

Debugging information

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

  • Version of devise-jwt in use => devise-jwt (0.8.0)
  • Version of rails in use => rails (6.0.3.3)
  • Version of warden-jwt_auth in use
  • Output of Devise::JWT.config
  • Output of Warden::JWTAuth.config
  • Output of Devise.mappings
  • If your issue is related with not getting a JWT from the server:
    • Involved request path, method and request headers
      `## Cors file
      allow do
      origins 'http://localhost:3001'

      resource '*',
      headers: %w(Authorization),
      credentials: true,
      expose: ["Authorization"],
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
      end
      end`

SessionsController

` class Users::SessionsController < Devise::SessionsController
respond_to :json
before_action :revoke_preexisting_token, only: %i[create destroy]

include ActionController::Cookies

def create
@user = User.find_by(username: params[:user][:username])

if @user&.valid_password?(params[:user][:password])
  token = encode_token({ user_id: @user.id, refresh_token: 'token' })
  cookies[:refresh_token] = { value: token, httponly: true, same_site: :none, secure: true }
  render 'sessions/logged?.json.jbuilder'

else
  render json: { message: 'Wrong username or password' }
end

end

def logged?
byebug
return unless cookies[:refresh_token]

token = JWT.decode(cookies[:refresh_token], ENV['devise_secret_key'])
@user = User.find(token[0]['user_id'])
render json: { message: 'no user is logged in' } unless @user
render 'sessions/logged?.json.jbuilder'

end

def delete
cookies.delete :refresh_token
render json: { message: 'log out success' }
end

private

def respond_with(resource, _opts = {})
render json: resource
end

def respond_to_on_destroy
head :ok
end

def refresh_token
cookies.encrypted[:refresh_token]
end

def revoke_preexisting_token
return unless refresh_token

RefreshToken.find_by(token: refresh_token)&.revoke

end

protected

If you have extra params to permit, append them to the sanitizer.

def configure_sign_in_params
devise_parameter_sanitizer.permit(:sign_in, keys: [:username])
end
end
`

Like Controllerr

`module Api
module V1
class LikesController < ApplicationController
respond_to :json
before_action :authenticate_user!
before_action :find_instrument
include ActionController::Cookies

  def index
    @likes = Like.all
    render 'likes/index.json.jbuilder'
  end

  def create
    byebug
    token = JWT.decode(cookies.signed[:refresh_token], ENV['devise_secret_key'])
    @user = User.find(token[0]['user_id'])
    @instrument.likes.create(user_id: @user.id)
  end

  def destroy
    @like.destroy
  end

  private

  def find_instrument
    @instrument = Instrument.find(params[:instrument_id])
  end

  def find_like
    @like = @instrument.likes.find(params[:instrument_id])
  end

  def revoke_preexisting_token
    byebug

    RefreshToken.find_by(token: refresh_token)&.revoke
  end
end

end
end
`

  • Response headers for that request
  • If your issue is related with not being able to revoke a JWT:
    • Involved request path, method and request headers

Hi @mariosknl ! The first thing you should consider is if you need JWT authentication. You said you're using cookies, so in fact I see no need and you can stick with raw devise library.

Thanks for your message in the first place. Well, I am setting the cookies in the browser. This is done via the sessions controller. So, I want to grab the current user id stored in the cookies in another controller. Can this happen somehow?

What do you mean I dont need raw devise library?

You JUST need devise, you don't need devise-jwt. devise-jwt is useful when you don't have cookies, as it allows authentication through HTTP headers. But if you can use cookies, you don't need to add this extra layer of complexity.

Closing for now, feel free to add more comments if needed