I'm trying to implement a refresh token with Vue 3 and Java for backend. It is working but interceptor keeps firing.
The logic: On every request there's a JWT Authorization header that authenticates the user. If that expires, there's a cookie endpoint in place ready to refresh the JWT.
I am using axios and interceptor response to check if the client gets a 401 to try and refresh the JWT. The cookie may be valid or not.
The problem is that the interceptor to refresh the JWT never stops firing, and I think I have something wrong with the synchronization of the requests. Below is my code:
Api.js:
import axios from "axios";
const instance = axios.create({
baseURL: "MY_URL",
});
export default instance;
token.service.js:
class TokenService {
getLocalRefreshToken() {
const user = JSON.parse(localStorage.getItem("user"));
return user?.refreshToken;
}
getLocalAccessToken() {
const user = JSON.parse(localStorage.getItem("user"));
return user?.accessToken;
}
updateLocalAccessToken(token) {
let user = JSON.parse(localStorage.getItem("user"));
user.accessToken = token;
localStorage.setItem("user", JSON.stringify(user));
}
getUser() {
return JSON.parse(localStorage.getItem("user"));
}
setUser(user) {
// eslint-disable-next-line no-console
console.log(JSON.stringify(user));
localStorage.setItem("user", JSON.stringify(user));
}
removeUser() {
localStorage.removeItem("user");
}
}
export default new TokenService();
setupInterceptors.js:
import axiosInstance from "./api";
import TokenService from "./token.service";
const setup = (store) => {
axiosInstance.interceptors.request.use(
(config) => {
const token = TokenService.getLocalAccessToken();
if (token) {
config.headers["Authorization"] = 'Bearer ' + token;
}
return config;
},
(error) => {
return Promise.reject(error);
}
);
axiosInstance.interceptors.response.eject()
axiosInstance.interceptors.response.use(
(res) => {
return res;
},
async (err) => {
const originalConfig = err.config;
if (originalConfig.url !== "/auth/login" && err.response) {
// Access Token was expired
if (err.response.status === 401 && !originalConfig._retry) {
originalConfig._retry = true;
try {
const rs = await axiosInstance.post("/auth/refreshtoken", {
refreshToken: TokenService.getLocalRefreshToken(),
});
const { accessToken } = rs.data;
store.dispatch("auth/refreshToken", accessToken);
TokenService.updateLocalAccessToken(accessToken);
return axiosInstance(originalConfig);
} catch (_error) {
return Promise.reject(_error);
}
}
}
return Promise.reject(err);
}
);
};
export default setup;
try clean el token authorization before send request refresh, by example in mutations(vuex)