Axios interceptor for JWT validation
Tags: javascript, nextjs, axios, interceptor
Published: 2024-03-16 18:14:32

We all used JWT at least once in our lives. In the minimum scenario we use JWT token for API requests to get any data. This kind of token is know as access token(AT) and it can store some property. But the **most important one is expire time**. So, we have to store that AT in the browser so that it can be send again when we make a request to the API. The work can be done from here but the problem arise if the token is valid for a long period of time. For this issue developer started to use refresh token(RT). 

1. **Access Token:** An access token is short lived token that is send as a bearer token inside the authorization header. The expire time is in between 1 minute to 15 minutes maximum.

2. **Refresh Token:** When an access token is expired, we make a call to a specific route for new access token. This route take refresh token as authorization header and do some serious validation to return an access token for API calls within the website and a new refresh token to store for the user in the browser to get the next new access token from the '/refresh' route.

For the front end call we usually use Axios or fetch API for calling the external API for data. For this guideline I am gonna use Axios and NextJS as a reference.

On the base line, Axios is used to make HTTP request to an API and get HTTP response in return. Interceptors are like middleman for this request and response. Whenever you gonna make a request its gonna go through the interceptor first. In that interceptor you can change the header object as you like. In our case AT is need to be add in the authorization header like below.
```
{
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2NGYwNzYzOGFlNjg4MDY4YzY1ODBkNzMiLCJwaG9uZSI6IjAxNSIsInJvbGUiOiJTVVBFUl9BRE1JTiIsImlhdCI6MTcxMDUwMzQ5NSwiZXhwIjoxNzExMTA4Mjk1fQ.STh0ZBiQVV
}
```
For our convenience, we make a fetcher function. that gonna get the access token from the local storage or cookie and add that token into the authorization header. That gonna look like something like this.

![code preview of the fetcher function](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/us76p8tci6av55ki6bmd.png)
Here the **checkAuth()** function get the header as option. In my application it was a hook that gonna utilize the interceptor mechanism of Axios.

## Axios Interceptor
Axios interceptor is like a middleware that gonna intercept the request and response of a http request and modify the header or data as per requirement.

So we made a interceptor that gonna get access token and evaluate if it is expired or not. If it is expired then it gonna call the **"/refresh-token"** route to get the new valid access token along with refresh token.


![code preview of the axios interceptor](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/9hwc5f5r9uhm1ewf5j4p.png)

Here, I used next auth for my project. **NextAuth provides** a hook called **useSession()**. This hook returns the data we stored in the session and a authentication state as status. In the **useEffect()** hook we called the request interceptor first. First argument of this function is callback function and the second argument takes the error handler. In brief we checked the AT validity then took a decision. if we need to fetch the refresh token we call the **useRefreshToken()** hook to get the new refresh token and set the info in the session storage using **useSession()** hook. 

But the **problem arise** when a page has 5 or 10 API call and all of them call the fetcher function thus the **useAxiosAuth()** hook. So all of them got the expired access token and call the **/refresh-token** route to get the refresh token. 

To resolve this problem we introduce the _promise based request solver_. 

![code preview of the queue of the pending requests](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/dx4278x0vrj2q5srhm44.png)
**addRequestToQueue()** will take all the request with invalid access token and place them in the **refreshQueue[]**. After that we will fetch the new access token from the **'/refresh-token'** route. Once we got all the AT. then we will resolve all the pending request that is waiting for fetching in the **refreshQueue[]**.

### Before the solution: 
5 API calls => 5 API call to the /refresh token route and 5 invalid calls to the final API with incorrect AT.
* Total 25 request to the backend server.
* If total user is 1000 then 25000 request.

### After the solution:
5 API calls => 1 API call to the /refresh token route => 5 valid calls to the final API with new correct AT.
* Total 6 request to the backend server.
* If total user is 1000 then 6000 request.

**76% reduction in calling the API.**

This is my first writing in my entire career, I apologize if anything is wrong. Suggest me the point of improvements, that I will truly appreciate. 

Thank you.