fix(proxy): prevent remote 401 from triggering local session logout

- Add x-sencho-proxy sentinel header to all proxied responses so
  the frontend can distinguish remote auth failures from local session
  expiry, breaking the logout loop when a node's api_token expires
- Add authMiddleware to all 5 /api/notifications endpoints that were
  missing protection (default-deny policy enforcement)
- Expand CSP to include connectSrc ws:/wss: and workerSrc blob:
  for WebSocket and Monaco editor worker support
This commit is contained in:
SaelixCode
2026-03-22 16:43:06 -04:00
parent 987fc3d339
commit aeefd79b50
3 changed files with 37 additions and 8 deletions
+11 -3
View File
@@ -26,8 +26,13 @@ export async function apiFetch(
const response = await fetch(url, { ...defaultOptions, ...fetchOptions });
if (response.status === 401) {
// Signal auth failure to AuthContext without a hard page reload
window.dispatchEvent(new Event('sencho-unauthorized'));
// Only fire the global logout event for local auth failures.
// When the response carries x-sencho-proxy, the 401 came from a remote
// Sencho node (expired/invalid api_token) — not from the user's own session.
// Logging out in that case creates an unrecoverable loop.
if (!response.headers.get('x-sencho-proxy')) {
window.dispatchEvent(new Event('sencho-unauthorized'));
}
throw new Error('Unauthorized');
}
@@ -66,7 +71,10 @@ export async function fetchForNode(
});
if (response.status === 401) {
window.dispatchEvent(new Event('sencho-unauthorized'));
// Same logic as apiFetch: only log out for local auth failures.
if (!response.headers.get('x-sencho-proxy')) {
window.dispatchEvent(new Event('sencho-unauthorized'));
}
throw new Error('Unauthorized');
}