DEV Community

Kartik Sharma
Kartik Sharma

Posted on

Automate Refresh Tokens with Axios Intercepters!

The Problem

A while back, I was working on a small project that interacted with the Salesforce API and performed CRUD operations on my objects. I was using React.js (with no backend setup, just a static frontend). However, I encountered a problem while working with the API. The access token I generate using the OAuth method is valid for only 24 hours! This means I have to manually generate a new token by making an OAuth API call every time I refresh the application.

I don’t like how my application is making unnecessary API calls to Salesforce OAuth to refresh the token, even when it hasn’t expired. To overcome this, I want to implement the following logic in my code:

axios.get('https://www.someapi.com/fetch-data').then((data)=> {
// doing something with the Data
},{}).catch((error)=> {
    if(error.response.statusCode === 401){
        // If Token Expired
        RefreshToken()
        window.alert("Session Expired Please Reload the Window!")
    }
})
Enter fullscreen mode Exit fullscreen mode

My logic is essentially this: if there’s a 401 response from the API endpoint, I make a refresh token API call, store the new token in local storage, and then prompt the user to reload the page to use the newly generated token for subsequent API calls. However, this approach relies on the user to perform an additional action, which could be automated to improve the user experience and avoid unnecessary interruptions.

Using Axios Intercepters

Let’s see it in action

axios.interceptors.response.use(
  (response) => response,
  async function (error) {
    const originalRequest = error.config;
    if (error.response.status === 401 && !originalRequest._retry) {
      if (isRefreshing) {
        return new Promise((resolve, reject) => {
          failedQueue.push({ resolve, reject });
        })
          .then((token) => {
            originalRequest.headers["Authorization"] = "Bearer " + token;
            return axios(originalRequest);
          })
          .catch((err) => {
            return Promise.reject(err);
          });
      }

      originalRequest._retry = true;
      isRefreshing = true;

      return new Promise((resolve, reject) => {
        initiateNewAccessTokenApi()
          .then((token) => {
            axios.defaults.headers.common["Authorization"] = "Bearer " + token;
            originalRequest.headers["Authorization"] = "Bearer " + token;
            processQueue(null, token);
            resolve(axios(originalRequest));
          })
          .catch((err) => {
            processQueue(err, null);
            reject(err);
          })
          .finally(() => {
            isRefreshing = false;
          });
      });
    }

    return Promise.reject(error);
  }
);

Enter fullscreen mode Exit fullscreen mode

Code Explanation

What I did was attach a middleware to every request that Axios makes, checking if any response comes back with a 401 HTTP status code. If it does, I re-initiate the access token by calling the refresh token API, store the new token in local storage, and automatically re-trigger all the previous API calls that were denied. That’s it! No more asking the user to ‘reload the window!’ 😸

I hope this helps and integrates well with your work!

Top comments (0)