What is the best approach for JWT Refresh Token?

Vahit Bayri
KoçSistem
Published in
6 min readSep 9, 2021

--

When their access token is expired, they will be able to use their refresh token to obtain a new access token.

Background

In this article, couple of approaches for implementation of Jwt Refresh Tokens will be discussed. In addition to the approaches, different refresh token implementations will be mentioned.

What is a Refresh Token?

Today, we use access tokens in order to protect our resources. Users who hasn’t got a valid access token will not be allowed to reach the protected resources like APIs. In other words, tokens are pieces of information that allow the authorization process to be performed. Access tokens carry the information to determine whether the authenticated user has access to the particular resources.

Access tokens typically have a limited lifetime. This is done for various security reasons: the first one, limiting the lifetime of the access token limits the amount of time an attacker can use a stolen token. In addition, the information contained in or referenced by the access token could become stale by time. After their lifetime is expired, these access tokens are useless.

When access tokens expire or become invalid, the application faces the problem of getting a new access token without forcing the user to authenticate again. To solve this problem, refresh tokens are being used to renew access tokens without prompting the user. Refresh tokens carry the necessary information to get a new access token.

Approaches

The main goal we want to accomplish for the refresh tokens is that make sure that clients will never have to be re-authenticated. When their access token is expired, they should obtain a new one with using refresh tokens.

1.LoginResponse with RefreshToken Approach ( Standard Approach)

One of the solutions of this problem is modifying the LoginResponse with a RefreshToken field. By this solution, every authenticated user will have their refresh token.

public class LoginResponse 
{
public LoginResponse (string token, IList<Claim> claims, string token)
{
this.Token = token;
this.Claims = claims;
this.RefreshToken = refreshToken;
}

public string Token { get ; }

public IList<Claim> Claims { get ; }

public string RefreshToken { get ; }
}

When their access token is expired, users will be able to use their refresh token to obtain a new access token. This process will be provided by an API called “Refresh”. After the controls of refresh token(If it is still valid and not expired yet), a new access token will be generated. As response, new obtained access token and refresh token will be returned just like response model Login.

public RefreshToken GenerateRefreshToken(User user)
{
RefreshToken refreshToken = new RefreshToken()
{
Token = GenerateRefreshToken(),
Id = user.Id
}
user.RefreshTokens.Add(refreshToken);
UserRepository.Update(user);
return refreshToken;
}

b ) Lifetime of Refresh Tokens

Refresh tokens should have longer lifetimes than access tokens since they are being used when the access tokens are expired to renew them. With this approach we will save time from renewing the refresh tokens every time we renew access tokens. They will not be for one time use. If this implementation is accepted, after the renewing the Jwt token process, the used refresh token should remain in the database/repository.

In the other hand, the longer lifetime means a higher potential for attackers. Assigning refresh tokens for only one-time use will be safer but requires a refresh token renewing process when the connected access token is being renewed.

c ) Creating Refresh Tokens with GUID

In the main approach System.Security.Cryptography.RandomNumberGenerator was used for creating random refresh token. Some suggests that we can use GUID for refresh tokens. In the other hand some other people believes GUID has a pattern inside and not random enough.

public string GenerateRefreshToken()
{
return Convert.ToBase64String(Guid.NewGuid());
}

d ) Multiple Refresh Tokens for Users

This option is more about the implementation of the concept than the security issues. If multiple device authentication from the same user is planned, single refresh token will not be enough. Approach should be assigning refresh tokens to user-device pair. A possible solution is to add a device identification field in your database and issue a refresh token per device.

2.Renewing Access Tokens with Watching Their Elapsed LifeTime

There are different standard fields(“claims”) that can be used inside a JWT claim set. One of them which is coded as “iat” identifies the time at which JWT was issued.

For more information on JWT Claims, please check JSON Web Token article.

Since these claims are keeping information about both when the token was issued and will be expired, we don’t need to wait for access token to be expired. Depending on the implementation, the renewing access token process may be updated as dependent on these claims.

var now = DateTimeOffSet.UtcNow;
var timeElapsed = now.Subtract(token.Claims.Single(x => x.Type == JwtRegisteredClaimNames.iat).Value);
var timeRemaining = token.Claims.Single(x => x.Type == JwtRegisteredClaimNames.exp).Value.Subtract(now);

With this approach, user’s token will not be expired due to lifetime and not responded as 401 Unauthorized. One of the disadvantages of this approach is the watching process. Elapsing time of the cookie should be inspected for every authenticated request.

Moreover this approach includes renewing the access token depending on the information in the access token. Under these conditions, it is possible to say that access token is renewing itself which means it is working like a refresh token at the same time. Since sending the refresh token for every authenticated request will create a security problem, this is a one more disadvantage.

LoginResponse with RefreshToken Approach

Advantages

  • Common Approach — Easy to make research since this approach is standard.
  • Security — Refresh token provides security since implementing it differs the tasks of access and refresh tokens. A Refresh token will be used only when an access token is expired.
  • Ease for future implementations — Provides ease for the possible future implementations like carrying the authentication mechanism outside of APIs.

Disadvantages

  • 401 Response — For this approach, access token should be expired to renew. Under these conditions, a 401 Unauthorized response should happen to renew the access token.

Renewing Access Tokens with Watching Their Lifetimes

Advantages

  • Automated flow — No need to wait for access token’s expiration
  • Easier for the client side — No need to implement one more token

Disadvantages

  • Watch implementation — Need to watch lifetime of access token for every authenticated request
  • Security Problem — Storing the tasks of refresh token to the access token will create security problems since access token is being sent for every authenticated request.

Sources

--

--