12

I've recently learned about JWT tokens, but I don't understand why I need them. Considering:

  1. HTTPS is enabled, thus the access token can't be stolen along the way. it's encrypted.
  2. If at anytime, the hacker finds a way to read incoming JSON responses from the server, then he can steal both tokens, since the access and refresh tokens are in the same response.
{status: "success", access: "abc", refresh: "def"}
  1. if at anytime, the hacker finds a way to read user's requests to the server, then the same is true: access and refresh tokens are sent in the same way (request headers), so if you can steal access token, you can do the same with refresh.
  2. if at anytime, the hacker finds a way to read the local storage of the user, then, same again, access and refresh tokens are saved in the same place (client's device), so the hacker can steal both of them.

So how does refresh tokens provide any extra security? Are they required?, and if no, how secure is it to use JWT Access tokens only, with long expiry dates (e.g. 3 months).

1 Answer 1

17

tl/dr: They key difference is that, unlike the JWT, the refresh token can be revoked. This allows it to have a longer liftetime and fill an important need in the JWT "ecosystem". Also, I think it is a little unusual to have both access and refresh token on every request/response. They should go to separate places.

The reason for short-lived JWTs

Imagine a JWT with a 3-month lifetime. During normal usage there is no option to revoke a JWT. Therefore, if the JWT is stolen, then the attacker will be able to act as the victim for 3 months (or however long is left on the token lifetime at the time of theft). This is why the JWT lifetime is kept nice and short.

The problem with short-lived JWTs

However, because the JWT is intended to have a short lifetime, getting a new JWT becomes an issue. If the JWT only has a lifetime of, say, a day (or even a few hours), then you need some way to automatically get a new one. Otherwise you will drive your users away because they are going to be irritated when they have to log back in to your site a few times a day.

Refresh tokens: the solution to short-lived JWTs

That is where the refresh token comes in. It can be used to generate a new JWT automatically. Therefore the refresh token's job is to log the user back in automatically so they don't have to put their password back in everytime the JWT expires. This makes life convenient for the user and gives a good balance between security and usability.

Securing long-lived refresh tokens

But why is it safe to have a refresh token that can last for months when the JWT can't? The answer is simple: It must be possible to revoke the refresh token so that the server no longer accepts it and won't issue new JWTs to someone who has it. This way if an attacker gets a copy of the refresh token it can be revoked, and the attacker will lose all access as soon as their short-lived JWT expires. Therefore you would invalidate all refresh tokens for a user in response to security events: if the system suspects a stolen refresh token, if the user changes their password, if the user changes their email, etc...

In essence, revoking refresh tokens is how you force a user to logout, which is something that is not possible with "standard" JWTs.

Bringing it all together

Finally, for the sake of completeness, the refresh token is revokable and the access token isn't for (typically) performance reasons. JWTs allow systems to validate user access without having to actually check a database or even have access to the user "table". This can be important for performance or, if nothing else, ease of development. A microservice that doesn't need database access is much easier to manage that one that does. Therefore your microservices can work with stateless JWTs exclusively, and then you can have a separate Auth server that manages the status and revokation of refresh tokens and JWT generation. In some cases this can be a convenient separation of concerns.

Finally, I think it is a little unusual to have both JWT and refresh tokens on every request and response. There may very well be systems that do that, and they aren't necessarily wrong, but typically the JWT goes along with every request for authorization/authentication, and the refresh token is only ever sent to the Auth server to get a new JWT. However some may send both always to alleviate some work for the client, as the backend services may use the refresh token as needed to get a new JWT and send that down to the client, so that the client doesn't have to manually refresh it.

3
  • 1
    The answer is spot on and complete. Adding simply the concept of separation of duties, where an access token's job is to provide the client with access to the user's data, whereas a refresh token's job is to manage the access token (generation, revocation, scoping, etc.)
    – Elie Saad
    Commented Jun 25, 2020 at 12:24
  • Can't I use the same jwt token to get a new token with a new expiration time? For example let's say the issued jwt token expiration time is 15 min and when 5 min is left, the microservice makes a call to auth service to get a new jwt token, and before getting a new jwt token, auth service will check if the old jwt token(where 5 min is left in expiration) is present in DB or not if present only then issue new jwt token with new exp time. Is it the correct approach or I am missing anything? Commented Nov 29, 2022 at 4:38
  • @conor I have a follow up post on your answer that you or the OP might be interested in security.stackexchange.com/questions/274267/…
    – ASP
    Commented Jan 25 at 6:45

You must log in to answer this question.

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