DEV Community

Cover image for Refresh Tokens
Afraz Khan
Afraz Khan

Posted on • Updated on

Refresh Tokens

In OAuth implementation, Authorization/Resource server assigns an AccessToken to each successfull user session. AccessToken is used by the client to make requests to the resource server.

RefreshToken is issued to the client by the authorization server to obtain a new AccessToken when the current AccessToken becomes invalid or expires or to obtain additional AccessTokens with an identical or narrower scope. Basically, RefreshToken provides the clients with a smooth experience where users are not required to repeat login step or some other authentication flow in order to get new AccessToken.

References
IETF
oauth.net
oauth0.com

How to use Refresh-Token?

  • After each successfull authentication request, Authorization/Resource server must generate 2 JWT tokens (AccessToken , RefreshToken).

    I talk here with JWT specification under consideration but tokens can be either JWTs or some other format of your choice. Its an implementation decision and not a topic to emphasize-on in this post.

  • Client will save both of the JWT tokens in the browser at some safe place.

  • RefreshToken JWT would have longer expiry (maybe 1 day) than AccessToken(could be 1-3 hours).

  • When AccessToken expires, the webapp/client would hit /api/auth/token endpoint with RefreshToken in request payload.

    /api/auth/token is supposed to issue new AccessTokens.
    Client does this silently without alerting the user.

  • The system will verify the RefreshToken and issue a new AccessToken without any user interaction involved.

refresh-tokens

RefreshToken Revocation

RefreshToken JWTs usually remain valid for longer durations like 1 day, 1 week or so and there is a chance that token could be compromised and misused beyond the user logout action if unexpired. To mitigate this potential threat, there should be some mechanism in place to invalidate the revoked but unexpired JWTs.

Some techniques are mentioned below:

JWT Whitelist

Here, the system maintains a whitelist of active RefreshTokens in some in-memory cache or database.

  • Every time a new RefreshToken request comes, the system looks for incoming RefreshToken in the in-memory cache or database.
  • If found, the system issues a new AccessToken else invalidates the request.

references: 1, 2, 3

JWT Blacklist

Here, the system maintains a blacklist of old/revoked refresh tokens in some in-memory cache or database. Revoked Tokens live on the blacklist until their expiry time is reached.

  • Every time a new refresh token request comes, the system looks for incoming RefreshToken in the in-memory cache or database.
  • If found, that means, the incoming RefreshToken is revoked and the system invalidates the request.

references: 1, 2, 3

Unique Claims

Every JWT has a claims list with it that includes information provided by user (email, name) as well as some attributes required by JWT Specification (iat, sub).
You can use any claim out of the JWT specification list to ensure token's authenticity. Use below technique:

  • Choose a token claim that is always unique at the time of token issuance.

    JWT iat is best option as its a unix time stamp.

  • Introduce a new field in your User database table where system will save the value of that claim for each new RefreshToken that system generates for each login request.

  • When system recieves a request to refresh the AccessToken. System will verify if iat value of incoming RefreshToken matches the current iat against the current user in the database.

  • If both iat values match then system issues new pair of AccessToken and RefreshToken otherwise 401 throws exception.

Some Stateless techniques

In the above 2 methods, database queries are involved to check the JWT revocation and this makes the token stateful. But depending on the severity of the JWT compromise that one foresees, there are many techniques out there to avoid any unwanted activity using stateless JWTs.
2 of them described below:

  1. Short Expiry times
    The straightforward stateless solution enforces the use of short expiry times for both AccessToken and RefreshToken like 10min expiry for AccessToken and 1hr expiry for RefreshToken. This simply reduces the time for any malicious activity if occurred.

  2. User-Defined Secret
    For each user, use a different secret to sign the RefreshToken JWT like secret = ENV.secret + user.password while generating the RefreshToken. At any time, if RefreshToken of a particular user is compromised, ask that user to reset their password and all old RefreshTokens issued to that user would be revoked automatically.
    See implementation: here

I hope this helps 🙂.

Top comments (1)

Collapse
 
mobinkazemi profile image
mobinkazemi

Helpful post, thanks! 👌