Here are my custom hooks:
const useRefreshToken = () => {
const { setAuth } = useAuth();
const refresh = async () => {
await axios.get('/refresh', {
withCredentials: true
}).then((response) => {
setAuth((prev: any) => {
return {
...prev,
role: response.data.role,
accessToken: response.data.accessToken
}
});
return response.data.accessToken;
})
}
return refresh;
};
const useAccessToken = () => {
const {auth} = useAuth()
const refresh = useRefreshToken();
const token = auth?.accessToken
return async () => {
if (token && isExpired(token)) {
await refresh();
}
}
}
const useAxiosPrivate = () => {
const refresh = useRefreshToken();
const { auth } = useAuth();
useEffect(() => {
const requestIntercept = axiosPrivate.interceptors.request.use(
config => {
if (config.headers !== undefined && !config.headers['Authorization']) {
config.headers['Authorization'] = `Bearer ${auth?.accessToken}`;
}
return config;
}, (error) => Promise.reject(error)
);
const responseIntercept = axiosPrivate.interceptors.response.use(
response => response,
async (error) => {
const prevRequest = error?.config;
if (error?.response?.status === 403 && !prevRequest?.sent) {
prevRequest.sent = true;
const newAccessToken = await refresh();
prevRequest.headers['Authorization'] = `Bearer ${newAccessToken}`;
return axiosPrivate(prevRequest);
}
return Promise.reject(error);
}
);
return () => {
axiosPrivate.interceptors.request.eject(requestIntercept);
axiosPrivate.interceptors.response.eject(responseIntercept);
}
}, [auth, refresh])
return axiosPrivate;
}
So I want to use useAccessToken()
hook to check if the current accessToken
in my state is not expired before requesting backend. If it is expired, then I need to use useRefreshToken()
to ask backend for new tokens and when the expired token will be replaced with the new one, I wanna send the actual request to backend.
But when I try to use those hooks like this:
const Api() {
const axiosPrivate = useAxiosPrivate()
const accessToken = useAccessToken()
const exampleApiCall = async (data: Data) => {
await accessToken().then(() =>
axiosPrivate.post(`/api`, data)
)
}
}
Then the request is sent with the old, expired accessToken
. The new one is used when I invoke the request again but it does not satisfy me