43

If I understand best practices, JWT usually has an expiration date that is short-lived (~ 15 minutes). So if I don't want my user to log in every 15 minutes, I should refresh my token every 15 minutes.

I need to maintain a valid session for 7 days (UX point of view), so I have two solutions:

  • use long-lived json web token (1 week)--bad practice?
  • getting a new json web token after the old one expires (JWT 15min, refresh allowed during 1 week)

I'm forcing the use of HTTPS.

The JWT standard doesn't speak about refreshing tokens. Is refreshing an expired token a good strategy?

30

Refreshing a token is done to confirm with the authentication service that the holder of the token still has access rights. This is needed because validation of the token happens via cryptographic means, without the need to contact the authentication service. This makes the evaluation of the tokens more efficient, but makes it impossible to retract access rights for the life of a token.

Without frequent refreshing, it is very difficult to remove access rights once they've been granted to a token. If you make the lifetime of a token a week, you will likely need to implement another means to handle, for example, the deletion of a user account, changing of a password (or other event requiring relogin), and a change in access permissions for the user.

So stick with the frequent refresh intervals. Once every 15-minutes shouldn't be enough to hurt your authentication service's performance.

  • 1
    so I can refresh an expired token ? why people recommend not to ? – Guillaume Vincent Apr 4 '16 at 7:12
  • ping @neil-smithline – Guillaume Vincent Jul 10 '17 at 14:45
  • 2
    Without a reference, it is hard to understand why something was recommended. Do you have references? The point of refresh token is to alllow revocation of access rights without hitting the authentication service too frequently. You can refresh the token (which does an access check) without needing to reauthenticate. – Neil Smithline Jul 11 '17 at 3:40
  • Ok so refresh tokens can also expire but are long-lived. They are only used to do revocation of access rights. So those token can be used to refresh an expired token. – Guillaume Vincent Jul 11 '17 at 10:39
  • 1
    @AliSherafat - as long as the refresh token is saved and still valid, then the app can get a new access token. If the refresh token is expired, then the user has been logged out due to being idle and will need to login again. – Neil Smithline Apr 5 '18 at 3:33
12

You should refresh the token every 15 minutes, but you don't need to let the user authenticate again to do so.

  • After authenticating, hand out a JWT that is valid for 15 minutes.
  • Let the client refresh the token whenever it is expired. If this is done within seven days, a new JWT can be obtained without re-authenticating.
  • After a session is inactive for seven days, require authentication before handing out a new JWT token.

This way you can for example require authentication after a user changed their password.

  • it's the solution I use for now, Let the client refresh the token whenever it is expired. My question is : is refresh an expired token is a good strategy ? – Guillaume Vincent Apr 13 '16 at 7:47
  • 6
    The client does not actually refresh the old token in the sense that it uses the old token to get a new one. Instead, the authentication layer knows the client was logged in recently and gives him a new token. You could implement this by using two JWTs, one that is valid for 15 minutes and one that is valid for 7 days. The long-running token can only be used to request a short-running token, and the short-running token can be used to access your API or whatever. This still makes it possible to revoke access every 15 minutes, while still having sessions of 7 days. – Sjoerd Apr 13 '16 at 7:55
  • @Sjoerd wont that complicate things to much? the server expecting 2 jwt.. and the client keeping 2.. – Gokigooooks Sep 30 '16 at 6:22
  • I guess using two JWTs is one of the options. Another one would be to use 1 JWT, with an exp of 7 days, and a custom shortExp of 15 minutes. As long as your middleware properly checks both expire values, and re-issues the token when the shortExp expires, this should be fine – Laurens Rietveld Oct 10 '16 at 8:43
  • 4
    How does refreshing a token even work? Do you store the username + password of the user on the client side? – Roger Far Mar 6 '17 at 3:24
5

You can get the access token configured for 7 days when the user authenticates. However it won't be the best practice security-wise because it would be harder to revoke access if needed. Of course it depends on your needs but the best practice is to also get the refresh token and user it to refresh the access token every period.

  • Everyone is talking about refresh tokens but won't show exactly how. Out of band requests? For a passive application that only pulls data from the server when interacted with, there's no way to do that unless timed, in which case you'll be facing other problems such as connectivity issues when a scheduled refresh request is attempted. – TheRealChx101 Aug 8 at 0:03
  • There are a bunch of implementations out there. Depends on which framework and language you are using.. Just a few examples: auth0.com/blog/… developer.okta.com/docs/guides/refresh-tokens/use-refresh-token – Igor Liv Aug 11 at 10:20
4

My setup is..

When someone logs in, generate a JWT with an exp of 5 days, with a custom field, useExp of 10 mins

When someone makes an authenticated request, the useExp must be in the future, unless they're asking for a new token

When someone makes an authenticated request for a new token, the useExp can be in the past, but the exp must be in the future. If valid, I'll generate them a new token as if they just logged in.

If both exp's are in the past, they must make an unauthenticated request to login with their email and password.

  • So each response comes with an overhead of checking for a newer token. – TheRealChx101 Aug 8 at 0:05
  • I don't understand your comment. What do you mean checking for a newer token? They aren't stored anywhere server side, thats the good thing about JWT. You just take the token given in the Authentication header, check its valid and not expired. A special case would be a refresh endpoint, which would allow expired token, but check an additional field, which contains a longer expiry time, in which the token can be refreshed. In this way, the server is only comparing a timestamp against the current time, it's hardly an overhead. – Michael Baldry Aug 8 at 10:41
  • What I meant was you have no control over the jwt's use. Your method is good and all but if the token ever got stolen (somehow) there'd be no way to terminate the session because the server does not reflect its state in any way. So, what I have done before is create an id (JTI field) for tokens and store that in the database. If there's no matching JTI token in the database then the JWT is rejected regardless of whether it's expired on not. This way, I can issue JWT as old as 90 days so application users don't get annoyed to sign in. Of course this depends on the type of application. – TheRealChx101 Aug 8 at 23:56
  • This gives me total control of the JWT and sessions because I can terminate a session at any given time. Your method might work well with financial and sensitive types of applications. For a chat/social application, it would be counter intuitive to ask the user to login every 5 days. I think the best way is to let the user know when there session will end and allow them to manually refresh the token say, 60 to 10 minutes before expiration. The overhead I was referring to was because I thought this refresh process was done automatically. – TheRealChx101 Aug 9 at 0:05
  • one of the great things about JWT is you don't need to keep track of it on the server-side. That said, they are flexible and can be used in many different ways, so it just depends on what you want to get out of it. The scenario of wanting to limit the life of a token while not annoying them with constantly having to sign in again is the exact case a token with an expiry and a refresh expiry solves. it expires after 10 mins, at which point the app needs to make a explicit request to the server to say "can I have another token?" - at which point it might say no, because things have changed. – Michael Baldry Aug 9 at 8:18
2

It seems like you are utilizing JWTs for session management. What you are wrestling with is a typical issue that comes up with this authentication scheme. JWTs are not ideal for session management requirements. You need various tricks to keep the session alive for longer (like others described), to revoke rights or log out. Here is an article that outlines what trade-offs you need to face with this setup.

If you can live with the compromises, JWTs are ok for session management. Should you need more granular control, take a look at cookie-based session management schemes.

1

Typically for JWTs you'll have an access token, that's valid for ~15 minutes, and a refresh token that is valid for longer (e.g. 24 hours).

To access API end points, the browser sends only the access token. If it receives a 401 HTTP status, it then refreshes it's token by submitting the refresh token to a specified end point, retrieves two new tokens (both refresh and access) and continues along.

Here's the wonderful thing. Both tokens have expiry dates, both tokens are signed -- hence you should always validate all tokens (regardless of access or refresh) using the same logic, before performing token specific validation.

1

For those who mentioned two JWTs (@keithRozario @Sjoerd) or one JWT but two fields (@Michael Baldry @Laurens Rietveld):

Let's called the two JWT or two fields access token and refresh token.

If the hacker get the access token somehow, then it is very likely that the refresh token is also leaked and the hacker can request the access token by using the refresh token. In that sense the access token's short expiration doesn't help much here.

someone suggested that a revocation list should be maintained at the server side so every request to refresh the token should be checked. Well, one of the major reason that people use JWT is that server doesn't need to maintain the session so it's more scalable. Doesn't the idea of maintaining the revocation list break this advantage?

One way that I can think of is to add another field to the access token to restrict refreshing the token to, say 30 minutes. So it can mitigate the loss even if both access token and refresh toke are leaked. But I'm not sure whether it's a good practice or not.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.