Signature verification raised
Mei152 opened this issue · 6 comments
Hello,
I realize this is not a help forum, but I have exhausted all efforts to figure out if my issue is caused by my own ignorance.
I am trying to set up this gem for two models, user
, and api_user
. user
will use regular Devise authentication, and api_user
will use jwt with the whitelist strategy. I have the log in and log out for api_user
working. The issue is that a get request for another resource results in "error": "Signature verification raised"
. If I add an extra character to the token in the request header, it will change the error to "error": "Invalid segment encoding"
, so at least I know the token is making it to decoding.
Judging from a previous issue like this in this repo, I am guessing you would want the following info:
irb(main):002:0> Warden::JWTAuth.config
=> #<#<Class:0x0000562b9d392ff0>:0x0000562b9d392e10
@config={
:secret=>"86630d90134bb9b5f105409635f61962761f59f2c9f3595c414cbca6ee1a4f47388c728b9fb61a12abe003b8e83cd0c57dd924f92162a005c001dd38480e8dd4",
:expiration_time=>3600,
:aud_header=>"JWT_AUD",
:mappings=>{:api_user=>"ApiUser"},
:dispatch_requests=>[
["POST", /^\/api_users\/sign_in.json$/],
["POST", /^\/api_users.json$/]
],
:revocation_requests=>[["DELETE", /^\/api_users\/sign_out.json$/]],
:revocation_strategies=>{:api_user=>"ApiUser"}
}
irb(main):005:0> Devise::JWT.config
=> #<#<Class:0x0000562b9d3f9c28>:0x0000562b9d3f9a48
@config={
:secret=>"86630d90134bb9b5f105409635f61962761f59f2c9f3595c414cbca6ee1a4f47388c728b9fb61a12abe003b8e83cd0c57dd924f92162a005c001dd38480e8dd4",
:expiration_time=>3600,
:dispatch_requests=>nil,
:revocation_requests=>nil,
:aud_header=>nil,
:request_formats=>{:api_user=>[:json]
Running Warden::JWTAuth::TokenDecoder.new.call(token)
on the Devise issued token does fail. However, decoding the token in jwt.io works fine, and the signature does pass verification using the same secret cited in the above configurations.
Here is what the request looks like in insomnia:
* Preparing request to http://localhost:3000/api/v1/things.json
* Using libcurl/7.67.0 OpenSSL/1.1.1d zlib/1.2.11 nghttp2/1.29.0
* Current time is 2019-12-15T01:53:10.268Z
* Disable timeout
* Enable automatic URL encoding
* Enable SSL validation
* Enable cookie sending with jar of 0 cookies
* Hostname in DNS cache was stale, zapped
* Trying 127.0.0.1:3000...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 3000 (#38)
> GET /api/v1/things.json HTTP/1.1
> Host: localhost:3000
> User-Agent: insomnia/7.0.5
> Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwic2NwIjoiYXBpX3VzZXIiLCJhdWQiOm51bGwsImlhdCI6MTU3NjM1MjY3NywiZXhwIjoxNTc2MzU2Mjc3LCJqdGkiOiIwZDUzYjZkYy0xNjBjLTRiNTktYTVmZS0wMDdmMWMyNjExNTYifQ.qjXqEddayVHhj4-ah6bxZW6eCGUZKm5n5jQCZgG41F
> Accept: */*
> Content-Length: 0
* Mark bundle as not supporting multiuse
< HTTP/1.1 401 Unauthorized
< Content-Type: application/json; charset=utf-8
< Cache-Control: no-cache
< X-Request-Id: 6b0a2886-826a-4643-8251-cbb949384ce2
< X-Runtime: 0.024096
< Vary: Origin
< Transfer-Encoding: chunked
* HTTP error before end of send, stop sending
* Received 52 B chunk
* Closing connection 38
If anyone can help point me in the right direction to solve this, that would be great!
Can't say for sure what fixed my issue. I tried many, many things. All I can say is that everything works at the moment. Sorry if I troubled anyone.
No worries. Feel free to post here any doubt you have in regard of devise-jwt
usage.
Thank you. Great gem. It solves my use case perfectly!
I have all the functionality for whitelisted strategy working properly but ran into an issue writing tests for edge cases. When a request is sent to an action protected with before_action :authenticate_api_user!
, and the token has been tampered with, the application blows up with an JWT::DecodeError
. We should be able to handle JWT::DecodeError
s gracefully.
The error is raised at this point at lib/jwt/decode.rb:97
JWT::JSON.parse(JWT::Base64.url_decode(segment))
rescue ::JSON::ParserError
raise JWT::DecodeError, 'Invalid segment encoding'
end
end
end
I tried to rescue the error in a logout scenario in the api_users devise sessions controller with the following:
def destroy
puts "hello form the destroy action"
begin
super
rescue #JWT::VerificationError, JWT::DecodeError => e
render json: { errors: ['Not Authenticated'] }, status: :unauthorized
end
end
But it does not work. I am not even getting the puts statement in the rails log. A similar puts in the sessions create action does show up in the log.
Here are my routes at this point in the project:
Rails.application.routes.draw do
devise_for :api_users,
path: 'api_users',
controllers: {
sessions: 'api_users/sessions', defaults: {format: :json},
confirmations: 'api_users/confirmations',
passwords: 'api_users/passwords',
registrations: 'api_users/registrations',
unlocks: 'api_users/unlocks'
}
devise_for :users,
path: 'users',
controllers: {
sessions: 'users/sessions',
confirmations: 'users/confirmations',
passwords: 'users/passwords',
registrations: 'users/registrations',
unlocks: 'users/unlocks'
}
get 'welcome/index'
namespace :api, defaults: {format: :json} do
namespace :v1 do
resources :things
end
end
get '/users', to: 'users/users#index'
root to: 'welcome#index'
end
Does anyone have an idea how to properly handle this situation? I am probably overlooking something obvious. I only half know what I am doing.
I appreciate any advice.
FYI, I noticed the following in the rails log when signing out an api_user:
Filter chain halted as :verify_signed_out_user rendered or redirected
I did some Googling, which guided me to add the following to my ApiUsers::SessionsController
:
skip_before_action :verify_signed_out_user , only: :destroy
Now the puts
statement in the destroy action shows up in the log, but the rescue still does not work.
Hey @Mei152 . If you are getting the puts
but not getting to the raise
, probably you are not having those exceptions... Please, open a new issue filling up the template with all the debugging information so that it is easier to help you. Thanks!