Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
759 views
in Technique[技术] by (71.8m points)

reactjs - Axios Interceptor Response Token Refresh API called but getting Token is expired regardless in refreshToken API & lator all APIs

my axios interceptor is:-

axios.interceptors.response.use((response, error) => {
  const originalRequest = response.config;

  if (response.data.status === 'Token is Expired' && originalRequest.url === '/api/refresh') {
    this.props.history.push('/logout');
    Promise.reject(error);
  }

  if (response.data.status === 'Token is Expired' && !originalRequest._retry) {
    originalRequest._retry = true;
    const playerToken = localStorage.getItem('accessToken');
    return axios
      .get('/api/refresh', {
        headers: {
          Authorization: `bearer ${playerToken}`,
        },
      })
      .then(res => {
        console.log('from refreshtoken', res);
        const stringRes = JSON.stringify(res);
        const parsedRes = JSON.parse(stringRes);
        const stringData = JSON.stringify(parsedRes.data);
        const parsedData = JSON.parse(stringData);
        const stringToken = JSON.stringify(parsedData.data);
        const parsedToken = JSON.parse(stringToken);

        if (parsedData.success == true) {
          localStorage.setItem('accessToken', playerToken);
          axios.response.config.headers['Authorization'] = `bearer ${parsedToken}`;
          return Promise.resolve();

          return axios(originalRequest);
        } else {
          this.props.history.push('/logout');
        }
      })
      .catch(err => {
        console.log('from refreshtoken', err);
      });
  }

  return Promise.reject(error);
});

My code is running but when my refresh token API is called first time, It also returns the same status "Token is expired" due to which i am logged out of the app. This is happening only in interceptor. When i am calling Refresh API outside of interceptor, it returns with a refresh token.

Does my code have mistakes? or it is some other coding fault entirely. Please answer & tell me the right way to do it & where do i place my interceptor?? Currently it is placed in a Component which is called just after login.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Usually the flow should be as such:

  1. making a regular request with accessToken
  2. request fails with status code 401
  3. axios interceptor catches it and makes request to token/refresh. from that response it gets a new access token.
  4. retries the original request.

So the code should looks like this (this is a working example from my app):

function isUnAuthorizedError(error) {
  return error.config && error.response && error.response.status === 401;
}

function shouldRetry(config) {
  return config.retries.count < 3;
}

function updateAuthToken(response) {
  localStorage.setItem('token', response.data.accessToken);
}

async function authInterceptor(error) {
  error.config.retries = error.config.retries || {
    count: 0,
  };

  if (isUnAuthorizedError(error) && shouldRetry(error.config)) {
    const response = await axios.post(`/token/refresh`, {});

    updateAuthToken(response);

    error.config.retries.count += 1;
    axios.defaults.headers.common.Authorization = `Bearer ${response.data.accessToken}`; // update the accessToken
    return axios.rawRequest(error.config); // retries the original request
  }
  return Promise.reject(error);
}

axios.interceptors.response.use(null, authInterceptor); // This indicates that authInterceptor will work only on request errors (status code >= 400)

Hopes this flow makes more sense.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...