There is a request in a protected route that should be processed only after verification have been processed. Access and refresh token are in cookies and are attached to all necessary requests.
After access token is expired, backend returns 400
, should process block with refreshing token
in axios interceptor, but first comes request from protected route, and then refresh
import axios from 'axios';
import { API } from '@/constants/api';
import AuthService from '@/services/AuthService';
export const axiosInstance = axios.create({
baseURL: API.base,
timeout: 15000,
withCredentials: true,
});
axiosInstance.interceptors.request.use(
async (config) => config,
async (error) => Promise.reject(error),
);
axiosInstance.interceptors.response.use(
async (response) => response,
async (error) => {
const config = error?.config;
if (error?.response?.status === 400 && !config?.sent) {
await AuthService.refreshTokenPair();
return axiosInstance.request(config);
}
return Promise.reject(error);
},
);
export default axiosInstance;
const ProtectedRoute = observer((): JSX.Element => {
const { isAuth } = userStore;
const handleUnauthorized = () => {
userStore.isAuth = false;
};
useLayoutEffect(() => {
const verify = async () => {
const verifyDetails = await AuthService.verifyAccessToken();
const details = await UserService.getUserDetails(verifyDetails?.id);
if (!details) {
handleUnauthorized();
return;
}
userStore.user = details;
userStore.isAuth = true;
};
verify();
}, []);
if (!isAuth) {
return <Navigate to={ROUTES.home.path} replace />;
}
return <Outlet />;
});
export default memo(ProtectedRoute);
Resolve by:
if (error?.response?.status === 401 && config && !config.sent) {
config.sent = true;
try {
await AuthService.refreshTokenPair();
return await axiosInstance.request(config);
} catch {
return await Promise.reject(error);
}
}
return Promise.reject(error);
and protected:
...
const verifyDetails = await AuthService.verifyAccessToken();
if (!verifyDetails) {
handleUnauthorized();
return;
}
...
}, []); // UseEffect deps
...