fix(auth): prevent logout on transient API failures

This commit is contained in:
2026-07-13 19:29:04 +05:30
parent 68829dc72b
commit 830883c6b7
2 changed files with 87 additions and 42 deletions

View File

@@ -12,6 +12,62 @@ const axiosClient = axios.create({
},
});
export const axiosAuth = axios.create({
baseURL: BASE_URL,
headers: {
'Content-Type': 'application/json',
},
});
let refreshPromise: Promise<string> | null = null;
const isInvalidSessionResponse = (error: unknown) => {
if (!axios.isAxiosError(error)) return false;
return error.response?.status === 401 || error.response?.status === 403;
};
const refreshAccessToken = () => {
if (!refreshPromise) {
refreshPromise = axiosAuth
.post(
'api/auth/refresh',
{},
{
withCredentials: true,
},
)
.then((response) => {
const accessToken = response.data?.access_token;
if (!accessToken) {
throw new Error('Refresh failed: no access token');
}
useAuthStore.getState().setAccessToken(accessToken);
return accessToken;
})
.catch((error: unknown) => {
if (isInvalidSessionResponse(error)) {
useAuthStore.getState().logout();
useAppStore.getState().clear();
if (typeof window !== 'undefined') {
window.location.href = '/login';
}
}
throw error;
})
.finally(() => {
refreshPromise = null;
});
}
return refreshPromise;
};
axiosClient.interceptors.request.use(
(config) => {
const token = useAuthStore.getState().accessToken;
@@ -49,31 +105,11 @@ axiosClient.interceptors.response.use(
originalRequest._retry = true;
try {
const response = await axiosAuth.post(
'api/auth/refresh',
{},
{
withCredentials: true,
},
);
const accessToken = response.data?.access_token;
if (!accessToken) {
throw new Error('Refresh failed: no access token');
}
useAuthStore.getState().setAccessToken(accessToken);
const accessToken = await refreshAccessToken();
originalRequest.headers.Authorization = `Bearer ${accessToken}`;
return axiosClient(originalRequest);
} catch (refreshError) {
useAuthStore.getState().logout();
useAppStore.getState().clear();
if (typeof window !== 'undefined') {
window.location.href = '/login';
}
return Promise.reject(refreshError);
}
}
@@ -82,11 +118,4 @@ axiosClient.interceptors.response.use(
},
);
export const axiosAuth = axios.create({
baseURL: BASE_URL,
headers: {
'Content-Type': 'application/json',
},
});
export default axiosClient;