17

From https://stackoverflow.com/a/7209263/1225328:

The idea of refresh tokens is that if an access token is compromised, because it is short-lived, the attacker has a limited window in which to abuse it.

I get it, but if the attacker accesses the refresh token, they will be able to get a fresh auth token, am I wrong? This seems to just postpone the long-lived tokens security flaw...

Concerning this point, you'll find in the same answer:

Refresh tokens, if compromised, are useless because the attacker requires the client id and secret in addition to the refresh token in order to gain an access token.

Then what's the difference between using a refresh token and simply resigning in? And how do you store the client id and secret if you don't want users to have to reenter them again?


As @FStephenQ pointed out, a refresh token can be used only once: an attacker will then be able to get a new auth token, but only once, and a short-lived one. But then, how do you obtain a new refresh token once you already used one? If you get a new one when you use one, an attacker will then be able to refresh their token too...


The actual question is: how to keep my users signed in? On the apps I use, once I signed in, I never have to sign in again: how do they proceed?

Community
  • 1
  • 1
sp00m
  • 47,968
  • 31
  • 142
  • 252

1 Answers1

18

A refresh token can only be used to refresh once, and it is only sent to the authentication server when the client's access token has expired. When a refresh token is used, the authentication server returns a new authentication token, and optionally a new refresh token. The idea is to allow using short-lived access tokens, while allowing a valid client to re-authenticate without forcing the user to login again.

If a refresh token is stolen, then it can be used once to get a valid access token by the attacker. When the client tries to refresh their token, their refresh token will be stale, and so will be rejected. They will then ask the user to login again, and the authentication server will give them a new access token and refresh token, and the stolen token will be invalidated.

F. Stephen Q
  • 4,208
  • 1
  • 19
  • 42
  • 4
    Thank you for these explanations. But there is still an issue: since a refresh token can be used only once, how do you obtain a new refresh token once you already used one? If you get a new one when you use one, an attacker will then be able to refresh their token too... – sp00m Oct 03 '15 at 09:36
  • 3
    The attacker would have to wait until their access token expired, if OAuth is implemented properly. And user re-authentication always trumps refresh tokens; when a user re-authenticates, the server (should) invalidate all previous access tokens and refresh tokens (for the client making the authentication request) and start a new "chain" of tokens. These two things combined give mean that a stolen refresh token will very likely be useless for the attacker, and attackers cannot have their own parallel chain of tokens (for long) without user credentials. – F. Stephen Q Oct 03 '15 at 13:08
  • 4
    Thanks again, I think I get it now. But another question then: if a user signs in with a browser, he'll get an access token and a refresh token (#1). Then, later, the user signs in with another browser (#2, e.g. at work), and refreshes his token #2 (since it expired for example). When he gets back home, he'll need to reauthenticate, because he used a refresh token at work, which invalidated all previous tokens. Did I understand correctly? How to avoid this behavior then? – sp00m Oct 15 '15 at 13:21
  • It doesn't change anything, even if you return new refresh token all the time it can be intercepted all the time. It doesn't change anything in terms of security. – Konrad Sep 24 '18 at 22:37
  • 1
    @Konrad I just spent a couple of hours extremely confused how a refresh token would solve token theft in a mobile env. You are absolutely correct, the only advantages of using a refresh token is the added control over the distributed tokens. The amount of articles getting this wrong is extremely confusing. – n0rd Aug 25 '20 at 10:40
  • @n0rd Use OAuth only if you absolutely have to. If you need API only for yourself (internal) it's not worth the hustle in most cases. It will save you hours or days of headaches. For token invalidation(long-lived tokens, password resets, logouts), I recommend using Redis. – Konrad Aug 25 '20 at 11:13
  • I just generate long-lived JWT tokens in one app and invalidate them with Redis for additional security when the user logs out or changes the password. – Konrad Aug 25 '20 at 11:18
  • @Konrad It's not an internal project, security is a priority. – n0rd Aug 31 '20 at 12:48
  • But if I have to invalidate a token,I have to make a DB call to check whether or not the token is blacklisted. Which defeats the purpose of JWT. – DollarAkshay Feb 16 '21 at 08:10