Comments (22)
If someone else happens to have this issue again, in my case it was because i already had Authorization
bearer token saved in my local storage from a different app (i was developing a react app on the same port) so it was trying to sign in setting an invalid token. So it was fixed by clearing out the local storage.
from devise-jwt.
The comment from waiting-for-dev is what helped me after all. Turns out, when devise_for is in a scope
, devise needs a namespace for the user param:
scope :api do
devise_for :users, as: :api, defaults: { format: :json }
end
will expect {"api_user": {"email": "[email protected]", "password": "password"}}
from devise-jwt.
So I might be doing something wrong with my sign_in flow and maybe my error doesn't have anything to do with jwt? Because im sending a POST to sign_in
passing e-mail and password in order to retrieve the token which then I'll use for requesting routes protected by authentication but that's where im getting the 401 error.
from devise-jwt.
The first thing an user does is send a request to sign_in
providing e-mail and password, at that point, the request is sent without an Authorization Header. I was expecting devise to return me a JWT token which I'd store within my front-end application (react redux in this case).
After that, every request to my API would have an Authorization Header Bearer <token>
from devise-jwt.
I guess that you had a wrong user
param. I don't remember now how devise uses namespaces and so in order to name scopes, but maybe it should have been something like staging_user
.
You are welcome. Happy this works for you not. Closing the issue, then.
from devise-jwt.
Hi there,
what does the folowing return?
Warden::JWTAuth.config
Devise::JWT.config
from devise-jwt.
Hi, thanks for your reply, there the results:
Warden::JWTAuth.config
#<#<Class:0x007fe6d41244f0>:0x007fe6d411e1b8
@config=
{:secret=>
"db70e50ec08feabaa1f05c65dadfc8057fb774052ff8fe7bc90b6d4001bfb681bbd6c26fbf06b77f39078270093948a5fd9ea09fac495fc9f7aab43241836dcf",
:expiration_time=>3 hours,
:mappings=>{:manager_api_v1_user=>User (call 'User.connection' to establish a connection)},
:dispatch_requests=>[["POST", /^\/manager\/api\/v1\/auth\/sign_in$/]],
:revocation_requests=>[["DELETE", /^\/manager\/api\/v1\/auth\/sign_out$/]],
:revocation_strategies=>{:manager_api_v1_user=>JWTBlacklist (call 'JWTBlacklist.connection' to establish a connection)}}>
Devise::JWT.config
#<#<Class:0x007fe6d58a0340>:0x007fe6d589b9d0
@config=
{:secret=>
"db70e50ec08feabaa1f05c65dadfc8057fb774052ff8fe7bc90b6d4001bfb681bbd6c26fbf06b77f39078270093948a5fd9ea09fac495fc9f7aab43241836dcf",
:expiration_time=>3 hours,
:dispatch_requests=>nil,
:revocation_requests=>nil,
:request_formats=>{}}>
Should the dispatch and revocation requests on Devise::JWT.config inherit from Warden config or nothing strange there?
from devise-jwt.
Should de dispatch and revocation requests on Devise::JWT.config inherit from Warden config or nothing strange there?
No, nothing strange there...
Your error comes from ruby-jwt library, specifically from this method.
In order to try to isolate the error, try to run the following with a token generated during a sign in:
Warden::JWTAuth::TokenDecoder.new.call(token)
from devise-jwt.
Because im sending a POST to sign_inpassing e-mail and password in order to retrieve the token which then I'll use for requesting routes protected by authentication but that's where im getting the 401 error.
How do you provide the token to the requests protected by authentication?
from devise-jwt.
Yes, that's the expected workflow.
from devise-jwt.
So how can i try to generate a token if the error is happening during sign_in?
from devise-jwt.
I don't understand your issue. In you first comment you say that you get the error in UserDecoder.new.call
, but that's not called during sign in.
What's exactly the problem? Are you getting a token after the sign in (in the response headers)? If not, to which URL are you requesting it?
from devise-jwt.
I'm sorry, maybe i didn't find where the error was being really raised, I just removed the rescue that led to a 401 response to see the real error being raised.
Here's a postman request:
That request, with valid credentials leads to a 401 error, traceback from server:
Started POST "/manager/api/v1/auth/sign_in" for 127.0.0.1 at 2017-11-08 09:25:23 -0200
(0.6ms) SET NAMES utf8, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
(0.5ms) SELECT `schema_migrations`.`version` FROM `schema_migrations` ORDER BY `schema_migrations`.`version` ASC
Processing by Api::V1::SessionsController#create as */*
Parameters: {"user"=>{"email"=>"[email protected]", "password"=>"[FILTERED]"}, "formats"=>:json, "session"=>{"user"=>{"email"=>"[email protected]", "password"=>"[FILTERED]"}}}
Completed 401 Unauthorized in 1ms (ActiveRecord: 0.0ms)
Here's how my routes are set up:
Rails.application.routes.draw do
prefix = Rails.env == 'staging' ? :manager_staging : :manager
namespace prefix, module: nil do
get '/ping', to: 'application#pong'
namespace :api, defaults: { formats: :json } do
namespace :v1 do
devise_for :users, path: :auth
end
end
end
end
Don't mind the namespace with null module, it's just that we ran dockerized applications that have the same base entrypoint.
My Controller, which inherits from devise due to the API namespacing:
module Api
module V1
class SessionsController < ::Devise::SessionsController
end
end
end
And last, rails routes returns me:
Prefix Verb URI Pattern Controller#Action
manager_ping GET /manager/ping(.:format) application#pong
new_manager_api_v1_user_session GET /manager/api/v1/auth/sign_in(.:format) api/v1/sessions#new {:formats=>:json}
manager_api_v1_user_session POST /manager/api/v1/auth/sign_in(.:format) api/v1/sessions#create {:formats=>:json}
destroy_manager_api_v1_user_session DELETE /manager/api/v1/auth/sign_out(.:format) api/v1/sessions#destroy {:formats=>:json}
from devise-jwt.
The only thing that devise-jwt
does to the sign in request is adding an Authorization
response header if the result is 200. But it can't change the response status to 401. When email/password are provided, the strategy doing the authorization is devise's own DatabaseAuthenticatable. I would recommend trying to debug there.
from devise-jwt.
Maybe you forgot to add database_authenticatable
module to your user model? If so, then it could be possible that the unauthorization comes from devise-jwt
, which is not able to sign in the user because there is no token to decode. In such case, just add database_authenticatable
to your user model.
from devise-jwt.
class User < ApplicationRecord
devise :database_authenticatable, :jwt_authenticatable, jwt_revocation_strategy: JWTBlacklist
end
Yeah, i thought the same but no... I did find something strange tho...in Devise::SessionsController
the method create:
# POST /resource/sign_in
def create
self.resource = warden.authenticate!(auth_options)
set_flash_message!(:notice, :signed_in)
sign_in(resource_name, resource)
yield resource if block_given?
respond_with resource, location: after_sign_in_path_for(resource)
end
warden.authenticate!(auth_options)
is what causes an error which leads to the 401 response, but he's calling Warden::Proxy.authenticate!
. Following that, i found that when warden executes _run_strategies_for
the instance variable @winning_strategies
is empty, so it can't determine which strategy to use.
Is that a configuration error perhaps?
from devise-jwt.
Ok, so in order to test things I moved my sign_in route to a main entry point:
Rails.application.routes.draw do
prefix = Rails.env == 'staging' ? :manager_staging : :manager
namespace prefix, module: nil do
get '/ping', to: 'application#pong'
namespace :api, defaults: { formats: :json } do
namespace :v1 do
end
end
end
devise_for :users
end
And a request to http://localhost:3000/users/sign_in
completed with 200 (then it got redirected to the rails welcome controller) but in the stack there was nothing being executed by jwt (the response headers didn't have a token) but i think thats because the redirection.
So I think it's not an issue within devise-jwt, maybe with devise not working properly on namespaced routes?
from devise-jwt.
Yes, it seems an issue with devise configuration. Inspect Devise.mappings
. Maybe you are using a wrong scope name (user
in your params).
from devise-jwt.
Now iI think I found at least a workaround by only configuring paths for devise:
routes.rb
:
Rails.application.routes.draw do
prefix = Rails.env == 'staging' ? :manager_staging : :manager
namespace prefix, module: nil do
get '/ping', to: 'application#pong'
namespace :api, defaults: { formats: :json } do
namespace :v1 do
end
end
end
devise_for :users, path: "#{prefix}/api/v1/auth"
end
But when i send a POST to the sign_in URL I'm not getting a token in response headers, and SessionsController is redirecting me (warden flow for jwt not triggering anything). I Think I'm missing some set up step to make devise-jwt work properly and i can't find on the readme. Is there any app sample I could look at? Do I need a custom SessionsController?
from devise-jwt.
You need to configure devise for json, so it doesn't redirect on success (step when you loose the token).
You can look at the fixture app used in tests.
from devise-jwt.
If I remember well, you need to add respond_to :json
to your controller, and configure devise to use json
as default route format (in the router). You don't need a custom SessionsController
.
from devise-jwt.
I managed to make it work, I'm assuming its a problem with devise and namespaces leading do some wrong argument provided when warden executes its strategies for authentication. Sorry for giving you trouble man and thanks for all the support!
from devise-jwt.
Related Issues (20)
- Auto removal of expired jwt token from AllowList table HOT 1
- Can't get JWT token when using devise and JWT for reset password feature HOT 7
- Devise Resource not Authenticated HOT 4
- Devise Resource not Authenticated and Authorization header missing HOT 2
- How to Avoid Session storage caveat HOT 4
- Session Store Caveat Solution? HOT 5
- [Question] Does the login function add jti value on existing database ? HOT 7
- Not getting the JWT token when signing in via a graphql-ruby mutation HOT 9
- JWT::DecodeError when passing token such as "Bearer test" HOT 7
- No content while trying to validate reset_password_token to recover password HOT 1
- current_user nil after authentication HOT 1
- Authenticate_user controller helper returns 401 regardless of token validity HOT 2
- Desive JWT import in application.rb throwing is error HOT 3
- Consider advising users to add this code to revoke the JWT on password reset HOT 3
- Feature Request: Dynamic Method for Setting JWT Expiration Time HOT 3
- Devise::JWT::TestHelpers not authenticate in rspec test HOT 4
- There is an issue with the handling of the `Authorization` HOT 2
- Error on sign_out with JWT::DecodeError (No verification key available) In Production Environment HOT 3
- version 0.12.0 does not properly add support for issuer and token_header HOT 1
- Error: SQLite3::SQLException: no such column: allowlisted_jwts.allowlisted_jwt_id HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from devise-jwt.