waiting-for-dev/devise-jwt

Retrieving stored JWT token for use in an external platform

augustosamame opened this issue · 4 comments

Expected behavior

Token should be stored somewhere (user table) so it can be used to authenticate 3rd party platforms

Actual behavior

Token is not saved so no way to send token to a 3rd party.

Steps to Reproduce the Problem

I may have a wrong understanding on how devise-jwt works. I have assumed the flow is the following:

frontend user logs in and JWT token is generated, sent to frontend and stored
frontend user makes subsequent calls adding Bearer {{token}} in Authorization header
token is matched against token saved in user table and user is authenticated

However in the case of devise-jwt I can't find any place where token is actually stored (no extra field in user table is created). So I'm assuming devise-jwt decodes on the fly and just compares token sent by frontend to the corresponding signed token library SHOULD generate for that user info.

This would mean:

a) a specific user logging in would always generate the same JWT token. How would denylist work in this case, as unique token being generated would always be denied?
b) how can I get the JWT token and use it to authorize 3rd party platforms? I would need to store it somewhere so that 3rd party platform can just read the value for the user instead of having to implement it's own JWT library.

I may be completely off on how this library works so I apologize in advance. Thanks for a great library!

UPDATE:

Did some testing and I find that logging the same user several times does NOT generate the same JWT token, which makes sense. But what is the claim that makes it unique? Is it expiration time?
If it's not unique, then when receiving the token in subsequent calls, how is the library able to match it against a user without storing it?

If I wanted to send the generated JWT token somewhere, would this be a good place to do it?

def on_jwt_dispatch(token, payload)
  send_generated_token_to_3rd_party(token)
end

Hi @augustosamame , no worries, this is the place to ask questions, too.

I recommend you to read this introduction to JWT so that you can understand how things work:

https://auth0.com/learn/json-web-tokens/

Basically:

token is matched against token saved in user table and user is authenticated

It's not how it works

Did some testing and I find that logging the same user several times does NOT generate the same JWT token, which makes sense. But what is the claim that makes it unique? Is it expiration time?

It's not any claim what makes the token valid. The token is signed so it can be recognized later by the server:

  • Server dispatches a signed token with some claims confirmed by the server itself.
  • The client sends the same token, with the same claims, later in time.
  • The server checks whether the token was signed by itself (only the server has the private key for that; if it changes it doesn't recognize the token).
  • If the server recognizes the token, it just belive its claims, as it had already been confirmed by itself.

How would denylist work in this case

The token has a claim called jti which is always unique. This is the only information about the token that we persist in some revocation strategies.

So, storing the token in the database would open the gates to some kind of attack, even if we encrypt it (i.e., rainbow attack). Furthermore, it's not necessary. In order for a 3rd party service to authenticate it just needs to go through the authentication process. The frontend can be seen as a 3rd party for what is worth it.

Hope that it helps.

ook commented

@waiting-for-dev Your answer is perfect. I recommand to add it into the README.md under a "how JWT works" or at least a link to this issue 👍🏻