GithubHelp home page GithubHelp logo

Comments (22)

marlonmantilla avatar marlonmantilla commented on August 17, 2024 17

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.

niuage avatar niuage commented on August 17, 2024 5

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.

elisoncampos avatar elisoncampos commented on August 17, 2024 1

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_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.

from devise-jwt.

elisoncampos avatar elisoncampos commented on August 17, 2024 1

The first thing an user does is send a request to sign_inproviding 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.

waiting-for-dev avatar waiting-for-dev commented on August 17, 2024 1

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.

waiting-for-dev avatar waiting-for-dev commented on August 17, 2024

Hi there,

what does the folowing return?

Warden::JWTAuth.config
Devise::JWT.config

from devise-jwt.

elisoncampos avatar elisoncampos commented on August 17, 2024

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.

waiting-for-dev avatar waiting-for-dev commented on August 17, 2024

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.

waiting-for-dev avatar waiting-for-dev commented on August 17, 2024

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.

waiting-for-dev avatar waiting-for-dev commented on August 17, 2024

Yes, that's the expected workflow.

from devise-jwt.

elisoncampos avatar elisoncampos commented on August 17, 2024

So how can i try to generate a token if the error is happening during sign_in?

from devise-jwt.

waiting-for-dev avatar waiting-for-dev commented on August 17, 2024

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.

elisoncampos avatar elisoncampos commented on August 17, 2024

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:

image

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.

waiting-for-dev avatar waiting-for-dev commented on August 17, 2024

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.

waiting-for-dev avatar waiting-for-dev commented on August 17, 2024

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.

elisoncampos avatar elisoncampos commented on August 17, 2024
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.

elisoncampos avatar elisoncampos commented on August 17, 2024

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.

waiting-for-dev avatar waiting-for-dev commented on August 17, 2024

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.

elisoncampos avatar elisoncampos commented on August 17, 2024

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.

waiting-for-dev avatar waiting-for-dev commented on August 17, 2024

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.

waiting-for-dev avatar waiting-for-dev commented on August 17, 2024

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.

elisoncampos avatar elisoncampos commented on August 17, 2024

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)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo 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.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.