4

So I've been trying to learn as much as I can about JWT tokenisation, and auth0 seems to be the defacto JWT information hub.

However, the more I read about refresh tokens, the more I cringe - the very idea of an "infinitely" refreshable (or at least a very long expiry) doesn't sit with me.

So here is what I've decided to implement.

The architecture of the system: 1. API (pure API layer, also the auth server at the moment) - creates the tokens and validates them 2. App layer (flask handling requests).

When a user tries to enter the app - they are sent to the login page. They enter their details, and these are sent to the /authorize endpoint on the API.

These details are validated and a token created with a claim containing: "iat" issued at "exp" expiry 30 mins "oct" original created time

As far as the auth server and API are concerned, this token will expire in 30 minutes.

Now on the App Layer, each request checks the token and sees whether there is less than 5 minutes left before expiry.

If it finds there is it creates its own JWT (signed with the same secret as the API knows). It uses the original JWT (about to expire) as a payload object, then sends it to an endpoint on the auth /refresh_token

The /refresh_token endpoint then validates the token, extracts the original token from the payload, validates that and if it's a valid token (hasn't yet expired). It then checks the original created time, and makes sure a max timeout (set by the customer of our App) hasn't been reached - this is a system hard limit of 12hrs (but our customers can opt for shorter total sessions). If those checks are OK, it creates a NEW token and sends it back to the App Layer.

In this way, my thinking is:

  • The Auth server can always trust this refresh request, because it must receive a trusted JWT that contains the JWT originally created by the Auth server. This means, it could only have been created by the App Layer (or any server that has the secret).

  • The Auth server doesn't infinitely hand out refresh tokens.

  • If the secret is compromised - you're up the proverbial anyway, and until you know it's been compromised, there isn't much you can do - of course we have IP checkers to ensure requests for JWTs come from trusted sources, but still - IP spoofing isn't difficult if the attacker knew what they were doing.

  • The App Layer, has the ability to stop sending refreshes by killing the user session - hence a compromised JWT would only be "dangerous" for up to 30 minutes.

A lot of people get very worked up about security, and rightly so - but would you say this approach provides adequate checks and balances?

If not, I would love to hear ideas, improvements in process etc. Security is definitely not my strong suit, so all help will be greatly appreciated!

Cheers.

3
  • Definitely not as active as Stack Overflow :)
    – Trent
    Commented Apr 13, 2016 at 6:28
  • Maybe you've already did it, but did you take a look to our landing talking about JWT? auth0.com/learn/json-web-tokens It has more content than jwt.io hope it helps!
    – user108010
    Commented Apr 18, 2016 at 16:51
  • @PabloLaurino - I most definitely did. In fact I tried out auth0 to expand my understanding and test. But, it was the fact that auth0 refresh tokens are infinitely refreshable that I decided to roll my own. Although, I'm still interested to hear from some experts on whether my approach is a good one or not.
    – Trent
    Commented Apr 19, 2016 at 8:27

1 Answer 1

1

Some thoughts, not meant to be critical per se, just providing feedback:

  1. No reason to have the app make its own JWTs. Just pass the client-delivered JWT along.

  2. This may not be what was meant but it is not a good idea to have some unavoidable delay in revocation. Should some compromise be detected around a specific JWT it needs to result in immediate declination, not just in the JWT being made nonrenewable.

  3. There is no benefit to picking some arbitrary window within an expiration period to do some special renewal behavior, vs just having a shorter expiration period. It's confusing and the ergonomics are no more helpful for users. The relevant policy decisions are around whether activity automatically lengthens the session (which would be enforced on every request, not just with 5 minutes left), and what happens on receipt of an expired token.

  4. Relatedly, machinery to "renew with less than 5 minutes remaining up to a limit of 12 hours" is no different from having a refresh token that has some lifespan and is checked on expiration of a authorization token. Then think about whether lifespans of 12 hours are really much different than lifespans of 24 or 48 or some other arbitrary number.

  5. Think about multi device access- multiple refresh + JWTs, or the same? and concurrent access from a single device. Think about other potential mechanisms for locking down utilization of a token, like binding the token to a specific IP or user agent.

  6. Think about whether multiple apps will ultimately be involved in this system.

Hope that's helpful.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .