Few months back, I wrote few articles about how to secure the Web APIs using different mechanisms. The focus of those articles were mostly on the authentication aspects. If you want to have look at them, below is the list of those articles:
- Securing .NET Core 3 API with Cookie Authentication
- Securing .NET Core 3 API Using JWT authentication
- Securing .NET Core Web App calling Web API using MSAL and Azure AD
- Angular App and Azure AD Protected web API using MSAL
- Protect .NET Core API Using Azure AD B2C and MSAL
I got some reactions on these posts from the readers. Some of them suggested to write post about how the refresh tokens can be used along with JWT authentication.
That’s why I am writing this article, to demo how the refresh tokens can be used with .NET Core web APIs. I will use the same code from one of the previous article. So we have a web application, which uses .NET Core Identity, and it has an AuthController, which issues tokens to authenticated users.
This article focusses on explaining why refresh tokens are generally used. The next article in this series will show a sample implementation using .NET 5 web API.
What is it?
Before proceeding further, let’s understand what a refresh token is.
When the caller is authenticated, they get access token. As long as the access token is valid and not expired, the caller can use it for accessing the application. But once the access token is expired, the caller is not allowed by the application. As explained in post about JWT, there is no way to immediately sign out the authenticated caller.
So, there can be two questions:
- What should be the appropriate duration for expiry of access token? If it is too long, there might be chance of misuse of that token. If it is too small, user would need to authenticate again to get new access token.
- And when the access token expires, how should user get the new token? Showing login screen again and gain every time the access token expires does not seem right option.
Generally, when a caller is authenticated by an application which supports bearer token flow, the issuer issues two different tokens:
- Access token and its expiry. The access token can be a JWT token or any other custom token type. This is the token which is used by caller to access the application. This token generally has a short lifetime, from generally in seconds.
- Refresh token and its expiry. The refresh token is special type of token, which has very long expiry, typically can range from few days to few months.
refresh token is a token which can be used to get a new access token when the current access token is expired, without user having to present the credentials again.
But if the caller has refresh token, it can be presented to the application and then the application can issue a new access token. This access token can be then used by caller to interact with the application.
What about lifetime?
Like access token, the refresh token also has expiry. Depending on the domain and requirements of your application, you can choose right expiry for the refresh token.
Generally access tokens are said to be short lived and refresh tokens are supposed to be long lived.
If the refresh token expires before its usage, the client will have to get themselves authenticated using their credentials.
What does it contain?
Generally, access tokens can have claims which are very specific the application for which this access token is required. So, what should we keep in refresh token?
A refresh token can have minimal information to identify the user and to generate the new access token. It may include some form of user identifier and optionally, location identifier or IP address of client. The important point to note is – the pattern of contents of refresh tokens should not be easily guessable.
You can choose the attributes based on your requirements and design of the application. Note that GUIDs are unique, but not random. That’s why for the purpose of this demo, we will use random generated 32 bits.
Active Tokens: One vs Multiple
Some systems do not allow having multiple refresh tokens together, while other systems might allow that. This decision may affect your system design.
As we have discussed before, the refresh tokens can be used to get a valid access token, without client having to present the credentials. So, what does it mean?
It means that if the refresh token is compromised, malicious party may get the access tokens and can access the protected resources. If a refresh token is compromised, there can be provision to revoke such refresh tokens. So, if the any party tries to present such “revoked” refresh token to get the access token, then the request is denied.
Also, one more thing can help to reduce the impact of compromised refresh token. Every time an access token is used, it should be revoked and new refresh token should be issued.
Furthermore, you can also choose to keep pairs of access token and refresh token pairs on server side, that way, server can identify the refresh token corresponds to the presented access token. This would make it harder for malicious parties to use the stolen tokens.
Where to store refresh tokens ?
As discussed before, the malicious parties may get access to the refresh token. So, this question also is very important. For your reference, you can have a look at the question posted on StackOverflow to know various perspectives.
As the current post focuses only on the sample implementation part, we will not discuss this question here. Also, we will store the refresh token in the cookie.
Sequence of Interactions
Let’s quickly have a look at how the whole flow would work:
- Unauthenticated client (either app or user) calls ‘Login’ API and provides appropriate credentials.
- If credentials are valid, the API would return access token and refresh token both in the response.
- The client would use access token to call the secured APIs. The API would successfully return the result if token is valid. If the access token is invalid, then API would return 401 unauthorized..
- The client can then use refresh tokens to get the new access token, without having to present the actual credentials. At this step, the used refresh token would be marked as used (or revoked) so as to avoid the misuse. A new refresh token would be issued and would be sent to client.
- The newly obtained access token can be used by Client to access the application
What is next?
In this article, we have seen what is refresh token and what is its need. In next article, I will try to show a demo implementation.
I hope you enjoyed this post. Let me know your thoughts.