In this post, we will learn about using Access token and Refresh token to secure web APIs. We will try to cover all the whys, whats and buts related token based authentication.
Why do we need access tokens in the first place?
- Access tokens help to improve a client-server user experience by reducing the number of authentication and authorization required.
- We do not want the client to enter their username and password credentials on every resource request.
- So, we rather create a unique access token once the client is validated the first time.
- The access token is unique in a sense that the server issuing this token puts a unique signature on the token. It can not be replicated by anyone else unless they have the signing signature key.
- This token is then sent to the client where it is stored locally.
- Once the client has this token, they no longer need to send their username and password for authentication/authorization. Rather they only send this access token on each request.
- The server checks if the token was generated by the server and is a valid one or not.
- Based on the validity, server decides if the request should be authorized or not.
- So, to sum up, the main reason for using an access token is to enable user to access resource without sending their user name and password on each request.
Why can’t the user send their username and password on each HTTP request?
- Of course we can have a system where the client sends user credentials in every HTTP request to the server. In fact, this mechanism has a name called “Basic Access Authentication“.
- However, this is not a secure and practical authentication process. It increases vulnerability when we are sending the username and password on each request.
- If the network is not secure, a hacker can listen to these requests and get the user’s credentials and abuse it.
What is the difference between Access Token and Refresh Token?
- Access token live for a short time span; maybe a few minutes or hours.
- On every HTTP request, the client sends the access token to the server. The server verifies if the user should access the requested resource based on access token validity.
- Refresh token live longer than access token. They can live on the client side for years or even forever.
- The refresh token is used only when the client’s access token has expired and wants to renew the access token.
Why can’t we have Access Token alone which never expires?
- If we save an access token which lives forever on the client side, this becomes an issue when a hacker gets access to the token.
- Since this token never expires, the hacker can make any number of request based on the access token they have acquired.
- Even if when the server figures out that a token has been compromised, the server cannot blacklist that single token.
- This is because the server signs all the Access token with same signature.
- So, in order to invalidate a single access token, the server has to invalidate all other access tokens.
- Imagine Facebook asking all of it’s 3.2 billion users to login again because your access token was compromised. Not practical eh?
- So, it is important to have access tokens which have a short life span like 5-10 minutes. This as it reduces the time window for the hacker to gain access to this token and misuse it.
Why can’t we have a short-lived Access Token alone?
- If we have a short-lived access token, this will lead to asking users to sign in with their credentials every few minutes.
- Again this isn’t quite practical.
So, how does a Refresh Token help?
- The main reason to use both access token and refresh token is to minimize the risks of a hacker requesting resource on behalf of somebody else.
- Client uses a refresh token along with the access token when making API calls.
- Client uses the refresh token only when the access token has expired and needs to be renewed.
- Whenever the access token has expired, client sends both the refresh token and access token to the server. Server validates that this is a valid request and rewards the client with a new access token.
- The client then uses this token to make subsequent requests.
- So, in this request flow, even if the hacker has access to access token, he cannot do much in a short time window.
- Also, since the refresh token is not sent on every request, the probability of refresh token being hacked is reduced.
- Furthermore, the server can easily invalidate the compromised token in this case. So, the system can force only the compromised account to login to the system again rather than asking all the users to do so.
- Users can also choose to have specific refresh tokens invalidated if they are using multiple devices to use the system.
Very interesting. So, what does the validation process look like using Access token and Refresh token to secure web APIs?
- Once a client is verified for the first time, the server generates an access token and a refresh token for the user.
- The server side saves the refresh token in database and the client side saves both the refresh token and access token values persistently.
- While the access token can be a standard JSON Web Token (JWT), the refresh token can be a simple GUID.
- On subsequent requests, prior to making a request, the client first checks if the access token has expired or not.
- If the token hasn’t expired, then the client makes API call with the valid access token.
- However, if the token has expired, the client should renew the access token first.
- So, the server receives a request to renew the access token in which the client passes both the refresh token and user’s id for verification.
- The server then looks up if there is a matching entry for refresh token and user id pair in the database.
- If there exists a valid entry, the server creates another access token for the client.
- The client then updates the new access token in it’s local database. Any subsequent calls to server are made with this new access token for requesting resource.
Hope this post helped you to make the decision regarding whether you should implement both the access token and the refresh token for securing your APIs.
Check out: How To Decode A JSON Web Token(JWT) In Dart