1

I have read a number of posts of many people expressing their confusion around the extra security gained from using an access token and a refresh token to control access to a resource API. Picking up from this post how-does-a-jwt-refresh-token-improve-security on this site; The author of the question made his case: if an access token can be stolen so can the refresh token, so what's the point of issuing a refresh token? The accepted answer is that unlike an access token, a refresh token can be revoked. If a hacker were to gain access to a long lived access token, there's no way to invalidate the access token(without invalidating access tokens of all users). Therefore, necessitating the use of short lived access tokens and revocable refresh tokens. Use cases for revocable refresh tokens include logging a user out from all sessions, user password change.

While I am convinced that a combination of refresh token and short lived access token makes the authentication/authorization process more secure, I think there is a better way to achieve the same result without the need for a refresh token at all. All we need to do is store the creation date of the access token in the token itself and create a table in the database to store (user id, revocation_timestamp) pair. Whenever we suspect an access token has been compromised, we update the revocation_timestamp to the current time. A hacker with a stolen access token will have access to the resource server for the short lifetime of the access token. When we receive an expired access token, we check in our database for revocation-timestamp corresponding to the user id in the token. If the token was issued later than the time in revocation-timestamp, we issue the user a new access token otherwise they have to supply their credentials. And that is it, the hacker is blocked. No need to store long refresh tokens in our database.

I would love to get feedback on my approach. Do we really need refresh tokens?

ADDITION

Another security feature of refresh tokens is that they can't be used twice. If a malicious user gained access to a refresh token and used it to get a new access token, that new refresh token would be invalidated when the legitimate user tries to use the old refresh token. This too can be achieved with just the access token. We will need to store the timestamp of issuance of latest access token in our DB. Whenever a request for a new access token is made, we compare the timestamp in the provided token with the timestamp of the most recent access token issued. If the timestamp in the provided token doesn't match that stored in our DB, we know this access token is being reused so we stop all active tokens from being able to generate new tokens by setting the revocation-timestamp in our DB to the current time.

The last bit that needs to be addressed is a malicious user continuously supplying the same old compromised token to the server thereby invalidating our legitimate user session repeatedly. In that case, we store another piece of information to capture the most recent date a user supplied their credentials. If the timestamp in the old token is more recent than the last time the user supplied their credentials, we prompt all users to login again when the compromised access token expires. If the last login date of the user is more recent than timestamp in the compromised token, we ignore the threat and keep our user logged in.

8
  • See stackoverflow.com/questions/38986005/… for some interesting reading on this subject.
    – mti2935
    Commented Jan 24 at 21:12
  • @mti2935 I have read through the stack overflow post: Because the refresh tokens are sent only to the authorization server, there's lesser risk of a malicious user gaining access to it unlike access tokens that are sent to resource servers that could be compromised. Otherwise, all other security benefits of refresh tokens can be achieved with just the access token alone.
    – ASP
    Commented Jan 25 at 7:29
  • What if the resource server is also acting as an authentication/authorization server (jwt web application), any benefits of refresh tokens)?
    – ASP
    Commented Jan 25 at 7:30
  • Your question is a little amorphous. "Do we need refresh tokens?" Yes, and the standards explain why. "Isn't my proposed alternative better?" Maybe, you don't give nearly enough info to come up with an opinion, and that has nothing to do with your title question. So, this really comes down to "why can't we combine access tokens and refresh tokens and make it possible to revoke access tokens?" or "why are access and refresh tokens split?" These are things we can answer from the standards. We can't really evaluate your high-level description of an alternative.
    – schroeder
    Commented Jan 25 at 9:19
  • @schroeder Writing focused questions can be challenging. Refresh tokens make it possible to 'revoke' access tokens while still giving a user a good UX. What I really want to know; firstly does my approach also solve this problem and two, are there any drawbacks / limitations in using my approach? I believe you can do some analysis if the approach can actually work from the high level description I have provided.
    – ASP
    Commented Jan 25 at 11:06

2 Answers 2

1

There is a lot of literature both from identity vendors / platforms and from the folks behind OAuth and OpenID Connect as to why refresh tokens are necessary. Here are some of the benefits

  1. Make access tokens short-lived thus reducing the threat they pose if they are stolen. Quoting Loginradius's documentation

The main purpose of using a refresh token is to considerably shorten the life of an access token. The refresh token can then later be used to authenticate the user as and when required by the application without running into problems such as cookies being blocked, etc.

The OP states that RT can be stolen. That's true and there's also a way to mitigate that. Quoting the same site

  1. Rotate Refresh Tokens

If a refresh token is compromised (someone else got their hands on it or, even worse -- steals it), the individual would not only gain access to the resources provided by the API but also the amount of time the access has been granted would be more. Now that's a dreadful scenario for developers and users alike.

Having said that, counter-measures such as Refresh Token Rotation and Automatic Reuse Detection help limit the destructive nature -- and highlight the benefits of these refresh tokens.

BTW this question has already been tackled here.

Lastly some great resources:

2
  • what if I say I can achieve the security of detection of reuse of refresh tokens another way with just the access token? Whenever we issue a new access token, we also store the timestamp of issuance in our DB. If a malicious user got access to the token, that access token will expire after a short time then we issue a new access token and store the new timestamp in our DB.
    – ASP
    Commented Jan 25 at 5:19
  • A legitimate user would also attempt to get a new token with the old token already used by the malicious user to generate a new token. The timestamp in this token will be less than that in our DB and we know the token is being reused.
    – ASP
    Commented Jan 25 at 5:19
0

This approach works (though the additional stuff you describe adds a ton of complexity and UX risk). You're basically taking the standard approach to "can we make refresh tokens be JWTs too?" (yes, but you need some complex system like this one) and tacking on "in that case, is there any need for them to be different from the access token?" (not that I can see, given you've already done the stuff needed for JWT-as-refresh-token to work in the first place).

You do run into problems with multiple clients, where each one should have a unique session lifetime and not trample each other, but that too can be addressed.

It must be asked though: in the end, is this worth it? You'll still have a small performance advantage over using opaque tokens for session access. However, the perf advantage over using them for refresh is negligible (you can reduce the number of tokens you transmit). The costs, though - in developer time to write this novel pattern, in security risk from doing something both novel and complicated in your auth code, and in UX risk from things like race conditions or clock skew or failing to address multiple clients properly all causing users to be unexpectedly signed out - seem to substantially outweigh the benefit.

1
  • I had to reread the OP's post after reading your answer to make sure I didn't miss anything, because from what I understood from his solution, it's just a 'revocation_timestamp' column on the users table. That doesn't seem complicated at all to me. If anything, it is considerably simpler than a access/refresh token system.
    – jpegoraro
    Commented Jun 23 at 3:32

You must log in to answer this question.

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