diff --git a/devfront/src/lib/apiClient.ts b/devfront/src/lib/apiClient.ts index 49b83cee..5a28cc72 100644 --- a/devfront/src/lib/apiClient.ts +++ b/devfront/src/lib/apiClient.ts @@ -27,17 +27,23 @@ apiClient.interceptors.request.use(async (config) => { apiClient.interceptors.response.use( (response) => response, async (error) => { - if (error.response?.status === 401) { - // 401 발생 시 로그인 페이지로 리다이렉트 - const isAuthPath = window.location.pathname.startsWith("/auth/callback"); - const isLoginPath = window.location.pathname === "/login"; - const user = await userManager.getUser(); - // 인증 토큰이 없는 경우에만 로그인으로 보낸다. - // 토큰이 있는데 401이면 권한/백엔드 정책 이슈로 간주하고 화면에서 에러를 노출한다. - const hasAccessToken = Boolean(user?.access_token); - if (!hasAccessToken && !isAuthPath && !isLoginPath) { - window.location.href = "/login"; - } + const status = error.response?.status; + const message = + error.response?.data?.error?.toString().toLowerCase() ?? + error.response?.data?.message?.toString().toLowerCase() ?? + ""; + const isAuthPath = window.location.pathname.startsWith("/auth/callback"); + const isLoginPath = window.location.pathname === "/login"; + const shouldRedirectToLogin = + status === 401 || + (status === 403 && + (message.includes("authentication required") || + message.includes("invalid session") || + message.includes("token is not active"))); + + if (shouldRedirectToLogin && !isAuthPath && !isLoginPath) { + await userManager.removeUser(); + window.location.href = "/login"; } return Promise.reject(error); },