Problemapp/api/auth/refresh/route.ts only rotates the CSRF cookie; there is no real access-token refresh, no POST // to the backend refresh endpoint, and no handling of expired refresh tokens. The comment in the code explicitly marks real token refresh as a TODO.
SessionTimeoutModal "extend session" button calls /api/auth/refresh which returns success but does not extend the server-side session.
- The axios single-flight refresh (
lib/api/refreshQueue/lib/api/axios.ts) also calls /api/auth/refresh on 401, gets no new access token, and therefore can never truly unblock queued requests.
- The
jti blocklist logic referenced from the backend has no frontend counterpart, so the client cannot know a token is revoked until the server rejects it.
Solution
- Implement the refresh route to exchange the session for a new access token against the backend.
- Propagate the new token into the axios instance and the auth store atomically with the queued-retry path.
- Surface a clear "session expired" state when the refresh token itself is invalid.
Acceptance Criteria
- Extending session in
SessionTimeoutModal results in a refreshed access token (verified via network tab).
- After a 401, queued requests retry with the new token and succeed.
- Expired refresh tokens redirect to login once, without toast spam.
npm run build passes.
Note for Contributors: Write a clear PR description. Include a network-tab screenshot showing the refresh call returning a new token and the subsequent replayed request succeeding.
Problem
app/api/auth/refresh/route.tsonly rotates the CSRF cookie; there is no real access-token refresh, noPOST //to the backend refresh endpoint, and no handling of expired refresh tokens. The comment in the code explicitly marks real token refresh as a TODO.SessionTimeoutModal"extend session" button calls/api/auth/refreshwhich returns success but does not extend the server-side session.lib/api/refreshQueue/lib/api/axios.ts) also calls/api/auth/refreshon 401, gets no new access token, and therefore can never truly unblock queued requests.jtiblocklist logic referenced from the backend has no frontend counterpart, so the client cannot know a token is revoked until the server rejects it.Solution
Acceptance Criteria
SessionTimeoutModalresults in a refreshed access token (verified via network tab).npm run buildpasses.Note for Contributors: Write a clear PR description. Include a network-tab screenshot showing the refresh call returning a new token and the subsequent replayed request succeeding.