Problem
The backend has used httpOnly cookie auth since bc64610 (feat: Redis-backed refresh tokens, JTI blacklist, httpOnly cookies) but the frontend was never updated to match.
The login endpoint returns { message, username } — no token in the body — yet the frontend was doing:
localStorage.setItem('access_token', data.access_token); // → stores "undefined"
Every subsequent request then sent Authorization: Bearer undefined, causing immediate 401s on all protected routes. The app was effectively broken for all authenticated flows.
Root Cause
POST /auth/login sets tokens as HttpOnly; SameSite=Strict cookies and returns only a success message. The frontend was written against the old bearer token pattern and was never updated when the backend switched to cookie auth.
Fix
- Remove all
localStorage token reads/writes from Login, Register, Dashboard, Profile, Inventory pages
- Add
credentials: 'include' to every fetch call so cookies are sent on cross-origin requests
- Add
withCredentials: true to all axios calls in service files (inventory.service.ts, location.service.ts, permissions.service.ts, uex.service.ts, api.service.ts)
- Replace
ProtectedRoute localStorage check with a real GET /auth/me call (httpOnly cookies are not readable from JS)
- Call
POST /auth/logout on logout so the backend revokes the refresh token and blacklists the JTI
Security Impact
This restores the intended security posture:
- Tokens are never accessible to JavaScript (XSS-proof)
SameSite=Strict prevents CSRF without needing CSRF tokens
- Logout properly revokes server-side session state via Redis
Problem
The backend has used httpOnly cookie auth since bc64610 (feat: Redis-backed refresh tokens, JTI blacklist, httpOnly cookies) but the frontend was never updated to match.
The login endpoint returns
{ message, username }— no token in the body — yet the frontend was doing:Every subsequent request then sent
Authorization: Bearer undefined, causing immediate 401s on all protected routes. The app was effectively broken for all authenticated flows.Root Cause
POST /auth/loginsets tokens asHttpOnly; SameSite=Strictcookies and returns only a success message. The frontend was written against the old bearer token pattern and was never updated when the backend switched to cookie auth.Fix
localStoragetoken reads/writes fromLogin,Register,Dashboard,Profile,Inventorypagescredentials: 'include'to everyfetchcall so cookies are sent on cross-origin requestswithCredentials: trueto all axios calls in service files (inventory.service.ts,location.service.ts,permissions.service.ts,uex.service.ts,api.service.ts)ProtectedRoutelocalStorage check with a realGET /auth/mecall (httpOnly cookies are not readable from JS)POST /auth/logouton logout so the backend revokes the refresh token and blacklists the JTISecurity Impact
This restores the intended security posture:
SameSite=Strictprevents CSRF without needing CSRF tokens