--- issue: "021" title: "Axios interceptor only retriggers token refresh for 401, not 403" severity: major domain: auth labels: [frontend, bug] status: open created: 2026-05-29 source: Doc vs Code Audit 2026-05-29 --- # 🟠 Axios interceptor only retriggers token refresh for 401, not 403 **Severity:** major **Domain:** auth **Labels:** frontend, bug ## Description `frontend/src/lib/axios.ts` (line ~105) only triggers the token refresh flow for `status === 401`: ```ts if (status === 401 && !isAuthRoute && !originalRequest?._retry) { // trigger refresh } ``` A `403` response (e.g., `EMAIL_NOT_VERIFIED`, a blocked account, or an under-privileged action) is not intercepted — it propagates as an unhandled error. Depending on how calling components handle errors, this may result in a blank screen or silent failure rather than an appropriate user message. ## Current Behavior Backend returns `403 EMAIL_NOT_VERIFIED` → interceptor does not retry or refresh → error propagates to the component. Some components may not handle this gracefully. ## Expected Behavior The interceptor (or a separate error handler) should: - On `403`: **not** attempt a token refresh (a 403 is an authorization failure, not an expired token) - But should surface the error clearly to the user (e.g., redirect to verify-email page for `EMAIL_NOT_VERIFIED` errors) ## Affected Files - `frontend/src/lib/axios.ts` — response interceptor ## References - [Doc vs Code Audit Report](../09%20-%20Audits/Doc%20vs%20Code%20Audit%20Report%20-%202026-05-29.md) — Finding M1