Search code examples
javascriptreactjsreduxaxios

Axios interceptor refresh token for multiple requests


I'll throw the http request because I'm calling the refresh token when it returns 401. After the refresh token response, I need to throw the previous request

SAMPLE Logın -> — 1 hours later— —> call product —> 401 —> call refresh token —> call product

I try this link a link and look this link a link but doesn't work.

Catch the 401 error

setInterceptors = () => {
        axios.interceptors.response.use(
            response => {
                return response;
            },
            err => {
                return new Promise((resolve, reject) => {
                    if (err.response.status === 401 && err.config && !err.config.__isRetryRequest) {

                        const originalRequest = err.config;

                        this.emit('onAutoLogin', originalRequest);
                    }
                    // throw err;
                });
            }
        );
    };

Call my action

jwtService.on('onAutoLogin', originalRequest => {
                    jwtService
                        .signInWithToken()
                        .then(res => {
                            if (res.access_token) {
                                originalRequest.headers['Authorization'] = 'Bearer ' + res.access_token;


Axios.request(originalRequest).then(response => {
                                    store.dispatch({
                                        type: ** MY PROBLEM İS HERE **
                                        payload: response.data
                                    });
                                });
                            }
                        })
                        .catch(err => {
                            jwtService.setSession(null); 
});

Solution

  • using this link I was able to solve the problem without triggering the redux store.

    let isRefreshing = false;
     let failedQueue = [];
    
           const processQueue = (error, token = null) => {
                failedQueue.forEach(prom => {
                    if (error) {
                        prom.reject(error);
                    } else {
                        prom.resolve(token);
                    }
                });
    
                failedQueue = [];
            };
    
    axios.interceptors.response.use(
                response => {
                    return response;
                },
    err => {
                    const originalRequest = err.config;
    
                    if (err.response.status === 401 && !originalRequest._retry) {
                        if (isRefreshing) {
                            return new Promise(function(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(function(resolve, reject) {
                            axios
                                .post('/fooUrl/refreshToken', {
                                    refreshToken: "fooToken"})
                                .then(({ data }) => {
                                    axios.defaults.headers.common['Authorization'] = 'Bearer ' + data.fooToken;
                                    originalRequest.headers['Authorization'] = 'Bearer ' + data.fooToken;
                                    processQueue(null, data.fooToken);
                                    resolve(axios(originalRequest));
                                })
                                .catch(err => {
                                    processQueue(err, null);
                                    store.dispatch(showMessage({ message: 'Expired Token' }));
    
                                    reject(err);
                                })
                                .then(() => {
                                    isRefreshing = false;
                                });
                        });
                    }
    
                    return Promise.reject(err);
                }
            );