diff --git a/backend/app/core/middleware.py b/backend/app/core/middleware.py index 83bdbae..fbe032d 100644 --- a/backend/app/core/middleware.py +++ b/backend/app/core/middleware.py @@ -149,6 +149,9 @@ async def _global_exception_handler(request: Request, exc: Exception) -> JSONRes def setup_middleware(app: FastAPI) -> None: + session_secret = settings.SESSION_SECRET_KEY or settings.SECRET_KEY + app.add_middleware(SessionMiddleware, secret_key=session_secret) + app.add_middleware(SecurityHeadersMiddleware) app.add_middleware(RequestIdMiddleware) @@ -168,9 +171,6 @@ def setup_middleware(app: FastAPI) -> None: expose_headers=["X-Message-Id", "X-Request-ID", "X-Process-Time"], ) - session_secret = settings.SESSION_SECRET_KEY or settings.SECRET_KEY - app.add_middleware(SessionMiddleware, secret_key=session_secret) - app.add_exception_handler(ServiceException, _service_exception_handler) app.add_exception_handler(StarletteHTTPException, _http_exception_handler) app.add_exception_handler(Exception, _global_exception_handler) diff --git a/frontend/src/lib/api.ts b/frontend/src/lib/api.ts index 83657fe..b3be5bb 100644 --- a/frontend/src/lib/api.ts +++ b/frontend/src/lib/api.ts @@ -87,19 +87,10 @@ async function refreshTokenIfNeeded(baseURL: string): Promise { } } +// Desktop reinstalls can leave stale refresh tokens in local storage while the backend +// identity/session store resets. Treat refresh 401 as terminal to break retry loops. function shouldInvalidateSession(error: unknown): boolean { - if (!(error instanceof RefreshTokenError)) { - return false; - } - if (error.status === 0) { - return false; - } - if (error.status >= 500) { - return false; - } - // Desktop reinstalls can leave stale refresh tokens in local storage while the backend - // identity/session store resets. Treat refresh 4xx as terminal to break retry loops. - return error.status >= 400 && error.status < 500; + return error instanceof RefreshTokenError && error.status === 401; } const extractErrorMessage = async (response: Response): Promise => {