0

I'm using axios as my data fetching library. The use case is that - the auth token expires every 30 minutes so once it expires, I've created an interceptor to catch the 401 and refresh the token. However, the issue is that every API call invokes the authentication API. Ideally, it should only happen once.

Here's the code that sets the default request headers

let refreshTokenPromise;

wrappedAxiosInstance.interceptors.request.use(
  async (config) => {
    const token = AuthService.getAuthServiceInstance().getAuthToken();
    // eslint-disable-next-line no-param-reassign
    config.headers.Authorization = `Bearer ${token}`;
    return config;
  },
  error => Promise.reject(error)
);

wrappedAxiosInstance.interceptors.response.use(
  response => response,
  async (error) => {
    const originalRequest = error.config;
    if (error.response.status === 401 && error.response.data.error === TOKEN_EXPIRED && !originalRequest._retry) {
      originalRequest._retry = true;

      if (!refreshTokenPromise) {
        // eslint-disable-next-line no-use-before-define
        refreshTokenPromise = api.auth.login().then((data) => {
          refreshTokenPromise = null;
          return data;
        });
      }

      // Can't get a reference to the token here. It never gets invoked
      const { token } = await refreshTokenPromise();
      console.log('result', token);
    }
    return Promise.reject(error);
  }
);

Here are sample API calls that consume this -

api.posts = {
  async list() {
    const response = await wrappedAxiosInstance.get(
      `${HOST}/policies`,
      // { headers: AuthService.getAuthServiceInstance().withAuthHeaders() }
    );

    if (response.status !== 200) {
      throw new ApiError(response.data);
    }

    return response.data;
  }
};

api.comments = {
  async list() {
    const response = await wrappedAxiosInstance.get(
      `${HOST}/controls`,
      // { headers: AuthService.getAuthServiceInstance().withAuthHeaders() }
    );

    if (response.status !== 200) {
      throw new ApiError(response.data);
    }

    return response.data;
  }
};

Essentially, the comments and posts both call the login. What I'm trying to achieve is that the call should only be made once.

Tarang Hirani
  • 560
  • 1
  • 12
  • 43
  • Does this answer your question? [How to avoid multiple token refresh requests when making simultaneous API requests with an expired token](https://stackoverflow.com/questions/60749813/how-to-avoid-multiple-token-refresh-requests-when-making-simultaneous-api-reques) – Phil May 05 '21 at 05:02
  • I can't seem to translate this to using async/await specially for the `refreshTokenPromise` part of it. This does not seem to work `const data = await refreshTokenPromise()`. Updated the question with the code now. – Tarang Hirani May 05 '21 at 05:29

0 Answers0