Monday 8 May 2023

Axios Interceptor on request does not wait for await function calls to be finished before proceeding with request

I have this interceptor code for all requests made using Axios. instance here is the Axios instance.

instance.interceptors.request.use(async (config) => {
  const tokens = JSON.parse(localStorage.getItem('users'));
  if (!tokens) {
    return config;
  }
  const accessTokenValid = Date.now() <= (tokens?.expirationTime ?? Date.now());
  if (accessTokenValid) {
    return config;
  }
  const refreshToken = tokens.refreshToken;
  if (!refreshToken) { 
    return config;
  }

  const response = await fetch(`${some-endpoint}/auth/refresh/token?token=${refreshToken}`);
  const newTokens = (await response.json()).data.data;

  localStorage.setItem('users', JSON.stringify(
    {
      accessToken: newTokens.access_token,
      expirationTime: Date.now() + parseInt(JSON.parse(newTokens.expires_in)) * 1000 - 600 * 1000,
      refreshToken: newTokens.refresh_token,
    }
  ));

  config.headers.Authorization = `Bearer ${newTokens.access_token}`;

  return config;
}, (error) => {
  console.error(error);
});

Then, the instance will be used like this.

    return instance.get(
      "/users/" + id,
      options
    );

where options look like this.

        {
          headers: {
            Authorization: `Bearer ${session.accessToken}`,
          },
        }

The problem with the code above is that the first request after the token expires will always fail. Then, the value in localStorage.users will be updated and the second request will succeed because the value has been replaced with the new access token.

I don't want to use an interceptor in response to retry the original request. I want to handle the token refresh on request. After investigating it turns out that the sequence of HTTP requests happening is as follows.

  • HTTP request to the endpoint users
  • Then, HTTP request to the endpoint for the token refresh

This tells me that the async/await part in the request interceptor isn't working. How can I make it so that HTTP requests must wait for the interceptor to finish running first (including awaiting any async functions) before running the HTTP requests itself?



from Axios Interceptor on request does not wait for await function calls to be finished before proceeding with request

No comments:

Post a Comment