Home > Net >  JWT authentication and the purpose of refresh token
JWT authentication and the purpose of refresh token

Time:02-11

I'm trying to wrap my mind around JWT authentication. I've read a lot of articles and SO questions, but some of them are getting old and I still didn't get satisfactory answers.

I've read this SO question and from José F. Romaniello's answer I understand that:

  • with refresh token client requests new access token before the old one has expired (it is normal, expected behavior)
  • on mobile apps tokens never expire

Also on auth0 it says:

You can request new access tokens until the refresh token is on the DenyList. Applications must store refresh tokens securely because they essentially allow a user to remain authenticated forever.

So what's the point of having time limited access token if refresh token can request for new access tokens forever?

Then I've read this SO question, which references the SO question from above. In his answer qre0ct says:

...assume that if Bob has compromised the refresh token, he would be using it to generate an access token (because access token is the only thing which is authorized to access resources through the APIs). As soon as Bob (attacker) requests with the newly generated access token because Alice's (genuine user) access token is still valid, the server would see this as an anomaly, because for a single refresh token there can be only one authorized access token at a time.

If we presume that it is normal for a client to request new access token at any moment (every hour, or every time the user opens the web application, as José F. Romaniello said), how will server distinguish if it's Alice or Bob who's making a request for a new access token? And why would this be anomaly?

Also, a lot of people say that the advantage of JWT authentication is that server doesn't make DB calls. But from above quotation from auth0, they mention DenyList. So I guess there must be a DB call on every request to check if the token is not blacklisted? Is the no DB calls thing a myth?

And if I have to keep record of blacklisted tokens, why not just use access tokens and blacklist them if necessary? I cannot understand the advantage of having two tokens, because if either one of them gets stolen, the thief can stay logged in forever (especially in the context of mobile apps where refresh token lasts forever)

Thanks in advance for your patience and time.

CodePudding user response:

After I've slept it over the things got clear(er).

My problem was that I was observing refresh token exclusively from the point of view of security. And from that point of view I still don't understand if/what advantages usage of refresh token brings.

What I've realized is that the purpose of refresh token is to reduce DB calls - instead of checking if access token is blacklisted on every client request, a DB call is made only when new access token is requested (so every access-token-lifetime), to verify if refresh token is blacklisted or the new access token can be issued.

CodePudding user response:

Couple questions here...

Might be easiest to answer this by starting with the intent of each token type - there's actually 3 types of token that all have different uses:

  • Access token
  • ID token
  • Refresh token

Access tokens are uses as bearer tokens on back-end API requests and are used for auth. They're often JWTs that don't contain PII. If an access token is compromised (e.g. if it's used in unencrypted request and intercepted) it would typically only have a lifetime of 10-15 mins, so there's a limited time frame where the attacker can use it.

ID tokens are received by public client apps and shouldn't leave the app. They're often JWTs and might contain PII e.g. a users name, email, phone so that the app can just get this information from the ID token without needing to make a back-end request.

Refresh tokens are used to streamline the authentication process for subsequent auths. Instead of having to sign-in with username & password/OTP, you can just use a PIN or biometrics to unlock the refresh token and perform a refresh token exchange to the IDP to get a new access and ID token (and potentially even new refresh tokens if performing refresh token rotation). Refresh tokens are opaque and should be stored securely on the app. There needs to be a bit more security around refresh tokens as they've often got a lifetime of several months whereas a single access token might only have a lifetime of a few minutes - typically 10-15 mins. If a refresh token is compromised, it can be used to get new access tokens until it eventually expires (potentially after multiple months). Refresh tokens should be stored securely on a device - typically the device key-store/chain and not leave the device. Historically refresh tokens have only been used in native apps where they can be stored securely on the device, and NOT in browser-based SPAs, but I think there might be some changes to these guidelines with the advent of refresh token rotation.


For question about using JWT authentication and that server doesn't make DB calls. What is meant here is that JWT auth is distributed. A JWT can be validated by simply verifying the digital signature without needing to make any subsequent network request (aside from an initial lazy loaded request to get the public signing key). Alternatively with opaque tokens, you'd need to make network request every time to some kind of data store to validate the token.


WRT blacklisted tokens, once an access token is issued, we typically don't call back to the IDP to validate the token (it's all distributed auth), so there's no concept of blacklisting an access token. A refresh token on the other hand can be blocked on the IDP, so when a user/device attempts a refresh token exchange (to get new access/ID tokens) the IDP can block the request if the refresh token has been revoked. Note: there are some fine-grained authZ strategies to block access tokens before they expire on your back-end, but it can get quite complex.

  • Related