Issue
I am developing react project using JWT authentication and write this code.
const service = axios.create({
baseURL: API_BASE_URL,
timeout: 60000
});
service.interceptors.response.use( (response) => {
return response.data
}, async (error) => {
const originalRequest = error.config;
// Remove token and redirect
if (error.response.status === 400 || error.response.status === 403) {
localStorage.removeItem(AUTH_TOKEN)
history.push(ENTRY_ROUTE)
window.location.reload();
}
// Unauthorized error token should refresh with access token
if (error.response.status === 401) {
const jwtToken = localStorage.getItem(AUTH_TOKEN)
const token = JSON.parse(jwtToken)
const refresh_token = token['refresh'];
const tokenParts = JSON.parse(atob(refresh_token.split('.')[1]));
// exp date in token is expressed in seconds, while now() returns milliseconds:
const now = Math.ceil(Date.now() / 1000);
if (tokenParts.exp > now) {
try {
const res = await service.post('/authentication/token/refresh/', {refresh: refresh_token});
localStorage.setItem(AUTH_TOKEN, JSON.stringify(res));
service.headers[TOKEN_PAYLOAD_KEY] = "JWT " + res['access'];
originalRequest.headers[TOKEN_PAYLOAD_KEY] = "JWT " + res['access'];
return service(originalRequest);
}
catch (error) {
}
}
else {
localStorage.removeItem(AUTH_TOKEN);
history.push(ENTRY_ROUTE);
window.location.reload();
}
}
return Promise.reject(error);
});
This is working well and have no errors, but I have something to ask. When the token is expired and some API is called, I get 401 status code to get access token with refresh token. And it returns the access token correctly.
But there is no way to re-call the failed API ( just called with expired access token ). That's why there are cases I could have no response from the backend ( Imagine, user clicks button, but no response, so he should click the button again to see the response. This is because of calling with new access token again )
This code is used in all parts of the project and I have many API callings, so it seems impossible to re-call failed API in each react components.
How can I fix this problem?
Solution
After some days of investigating my code, I finally found the answer.
Let me write my code and hope it will be helpful.
let refreshToken;
...
if (tokenParts.exp > now) {
try {
if (!refreshToken) {
refreshToken = service.post('/authentication/token/refresh/', {refresh: refresh_token}).then(token => {
refreshToken = null;
return token;
});
}
return refreshToken.then(res => {
localStorage.setItem(AUTH_TOKEN, JSON.stringify(res));
service.defaults.headers[TOKEN_PAYLOAD_KEY] = "JWT " + res['access'];
originalRequest.headers[TOKEN_PAYLOAD_KEY] = "JWT " + res['access'];
return service(originalRequest);
})
}
catch (error) {
}
}
else {
localStorage.removeItem(AUTH_TOKEN);
history.push(ENTRY_ROUTE);
window.location.reload();
}
This prevents multiple token refresh API request and surely made the failed API call again with new access token.
Answered By - seagulls0125 Answer Checked By - Marilyn (PHPFixing Volunteer)
0 Comments:
Post a Comment
Note: Only a member of this blog may post a comment.