ASP.NET Core 2.2 REST API #13 — Refreshing JWTs with Refresh Tokens

Theodoros Ntakouris
3 min readJul 23, 2019

--

Up Next: Running in Docker

Let’s change our IdentityController in order to issue refresh tokens.

Let’s add one more property to our "JwtSettings" , called "TokenLifetime": "00:00:45" (45 seconds — just for testing, you should have at least 5 minutes for a production scenario). Let’s update our JwtOptions to include this token lifetime property. we will update our MvcInstaller to use some new token validation parameters and add a singleton TokenValidationParameters:

The next step would be to alter our AuthSuccessResponse to include a refresh token, as well as our AuthenticationResult class, making sure to include the actual data back, on the /register and /login endpoints.

We can go ahead and create a new endpoint /api/v1/identity/refresh using our already-known strongly typed route best practises, creating contract objects on demand:

Pretty clean as usual

Refreshing the token

We’re first going to create a helper method that is going to return who is the one that owns the token( ClaimsPrincipal )while also checking if the JWT is signed with a secure algorithm.

Let’s create a new RefreshToken domain class. We will use this for the database as well.

The Dates are there for auditing purposes and the JwtId is the JWT that this refresh token is bound to.

You might want to invalidate all the refresh tokens for example, when the user changes his email.

Add the table to EF by using a DbSet<RefreshToken> and then add and apply the new migration.

The next part is lengthy, but it contains all the checks we need to do about token validity:

  • JWT authenticity, validity, security algorithm and claims principal check
  • Check that the JWT is expired (not mandatory, but we will use this to have some stricter security constraints — the user could just use the previously issued token)
  • Check if the refresh token is bound to the current JWT token id
  • Check if the refresh token is actually saved in the database
  • Check if the refresh token is not expired, used or invalidated

After all these checks we can just flag the token as Used , save it to the database and issue a new token pair for our user.

The final part would be to update our GenerateAuthenticationResultForUserAsync method to issue and save refresh tokens as well.

We just hardcoded the 6 months expiry date for the refresh token, but you can make this configurable as well.

You can check that if you wait 45 seconds for the first token to expire, sure enough, you get a new token pair back.

If you try to do some illegal operation, like re-use the previous refresh token, you get the corresponding error message:

Up Next: Running in Docker

Code is available on Github and the instructional videos are located on YouTube.

Keep Coding

--

--

No responses yet