Search code examples
reactjsreduxaxiosmiddlewareredux-middleware

Redux middleware refresh token gets called after Axios request in the action creator


I'm creating a redux middleware to refresh the token before any request if the token is expired.
The problem is that after the first call I always get error 400 bad request, but if did another call (It's a pagination requrest) it works fine because the token was refreshed.
I noticed that the Axios request gets fired before the new token comes in and before setting the new Axios Authorization header, so I tried to make the middleware async-await, but still no luck ...

import {
    getJWT,
    isTokenExpired
} from "../util/helpers";
import Cookies from "js-cookie";
import axios from "axios";

const refreshTokenMiddleware = store => next => async action => {
    if (!action.excludeFromRefresh) {
        const token = getJWT();
        if (token && isTokenExpired()) {
            try {
                const { data } = await axios.post("auth/refresh");
                axios.defaults.headers.common[
                    "Authorization"
                ] = `Bearer ${data.data.access_token}`;
                Cookies.set("AppToken", data.data.access_token);
                next(action);
            } catch (error) {
                console.log(error);
            }

        } else {
            next(action);
        }
    } else {
        next(action);
    }
};

export default refreshTokenMiddleware;

I also suspect that the Axios request gets called with the old Token the first time.
What am I doing wrong here?

=====================

Edit

I tried to ditch the middleware all together and implement axios interceptors, since the middleware doesn't catch the axios request ...

axios.interceptors.request.use(
    function(config) {
        // Do something before request is sent
        if (
            config.url !== "auth/refresh" &&
            config.url !== "auth/login" &&
            config.url !== "auth/register"
        ) {
            const token = getJWT();

            if (token && isTokenExpired()) {
                axios.post("auth/refresh").then(res => {
                    config.headers.Authorization = `Bearer ${res.data.data.access_token}`;
                    console.log(
                        "Inside the refresh in interceptor",
                        res.data.data.access_token
                    );
                    return config;
                });
            }
        }
        return config;
    },
    function(error) {
        // Do something with request error
        return Promise.reject(error);
    }
);

But that also doesn't seem to work, the request fires with the old Token in the Authorization header on the first time.

What can I do?


Solution

  • For anyone interested who may come across this post, I managed to solve my issue using this Axios interceptor ... https://gist.github.com/Godofbrowser/bf118322301af3fc334437c683887c5f