Authenticate_user controller helper returns 401 regardless of token validity
michaelrevans opened this issue · comments
I have successfully set up Google omniauth with Devise to log a user in and used the custom JWT generator described in #3 to return a JWT to the client. Passing that token back in the Authorization
header as Bearer <token>
, however, always returns 401 Unauthorized when the authenticate_user!
before_action is used.
To Reproduce
config/routes.rb
Rails.application.routes.draw do
devise_for :users,
controllers: { omniauth_callbacks: 'api/v1/users/omniauth_callbacks' },
defaults: { format: :json },
path: "api/v1/users"
get 'health-check', to: 'health_check#show'
end
app/controllers/api/v1/users/omniauth_callbacks_controller.rb
class Api::V1::Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def google_oauth2
@user, token = User.from_omniauth(request.env["omniauth.auth"])
response.headers["Authorization"] = "Bearer #{token}" # this works as intended and the token is returned to the client
render json: { message: "Success" }
end
def failure
render json: { error: "Failure" }
end
end
app/models/user.rb
class User < ApplicationRecord
include Devise::JWT::RevocationStrategies::JTIMatcher
devise :omniauthable, :jwt_authenticatable,
omniauth_providers: %i[google_oauth2],
jwt_revocation_strategy: self
validates_presence_of :uid, :provider, :jti
validates_uniqueness_of :jti
def self.from_omniauth(auth)
# again, this works as intended and can create a new user with a token, as well as log an existing user back in and generate a token
user = find_or_initialize_by(provider: auth.provider, uid: auth.uid)
user.email = auth.info.email
user.name = auth.info.name
user.image_url = auth.info.image
token, payload = Warden::JWTAuth::UserEncoder.new.call(user, :user, "")
user.jti = payload["jti"] # this successfully stores the jti and it matches the jti in the decoded token that the client sends back in the Authorization header
user.save
[user, token]
end
end
app/controllers/health_check_controller.rb
class HealthCheckController < ApplicationController
before_action :authenticate_user! # this fails, despite giving a valid JWT in the Authorization header
def show
render json: { message: 'Success' }.to_json
end
end
Current behavior
401 is returned by authenticate_user!
even when a valid token is sent in the Authorization
header.
Expected behavior
authenticate_user! should pass when a valid taken is sent
Desktop (please complete the following information):
- OS: MacOS Ventura
- Browser Chrome
- Version 110
Additional information
Sending the request via cURL
has given an error message about the wrong aud
, so I also tried adding jwt.aud_header = ''
to the configuration, but to no avail.
curl http://localhost:5555/health-check \
> -H 'Content-Type: application/json' \
> -H 'Accept: application/json' \
> -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJqdGkiOiI0NDIzYzBhMy1iZTYzLTQzMzgtYTlmNC05YjBhZGNjZGI5ZTAiLCJzdWIiOiIiLCJzY3AiOiJ1c2VyIiwiYXVkIjoiIiwiaWF0IjoxNjc2OTA5NDQyLCJleHAiOjE2NzgxMTkwNDJ9.T3jxQzGdpbdzDZ41CHa3oVOzZ04kaDsrchK_H1AcGNg'
{"error":"wrong aud"}
I'm sure the problem lies on my side, I find it unlikely this is a bug, but I'm at a loss as to what to try next in order to solve my problem.