Summary
The frontend WebSocket client sends a session: 'cookie-auth' marker instead of the actual JWT token during WebSocket authentication. However, the backend WebSocket handler expects an actual JWT token in the token field. This mismatch causes WebSocket authentication to fail.
Vulnerability Details
- CWE: CWE-287 (Improper Authentication)
- CVSS Score: 6.5
- Files:
- Frontend:
src/services/api.ts (line ~210)
- Backend:
backend/app/routers/websocket.py (line ~161-168)
Current Behavior
Frontend (src/services/api.ts):
this.ws?.send(JSON.stringify({
action: 'authenticate',
// Don't send actual token - server will validate via cookie on the HTTP upgrade
session: 'cookie-auth'
}));
Backend (backend/app/routers/websocket.py):
token = auth_message.get("token") # Expects 'token' field
if not token:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return
payload = verify_websocket_token(token) # Validates JWT
Problem
- Frontend sends
{action: 'authenticate', session: 'cookie-auth'}
- Backend looks for
auth_message.get("token") which is None
- Backend closes connection due to missing token
- WebSocket real-time features don't work
Remediation Options
Option A: Backend accepts cookie-based auth (Recommended)
Modify backend/app/routers/websocket.py to check for HttpOnly cookie if no token in message:
token = auth_message.get("token")
# If no token in message, try to get from cookie (for cookie-auth mode)
if not token and auth_message.get("session") == "cookie-auth":
# Extract token from cookie that was sent during WebSocket upgrade
# Note: WebSocket upgrade is an HTTP request, so cookies are available
cookie_token = websocket.cookies.get("access_token")
if cookie_token:
token = cookie_token
if not token:
await websocket.close(code=status.WS_1008_POLICY_VIOLATION)
return
Option B: Frontend sends actual token in test mode
Modify src/services/api.ts to send the actual token when available:
const tokenMarker = sessionStorage.getItem(TOKEN_STORAGE_KEY);
if (tokenMarker && tokenMarker !== 'cookie-auth') {
// Test mode: send actual token
this.ws?.send(JSON.stringify({
action: 'authenticate',
token: tokenMarker
}));
} else {
// Production: signal cookie auth
this.ws?.send(JSON.stringify({
action: 'authenticate',
session: 'cookie-auth'
}));
}
Then backend needs to handle both cases.
Testing
- Login via OAuth
- Navigate to a page that uses WebSocket (dashboard with real-time updates)
- Verify WebSocket connection is established and authenticated
- Check browser console for WebSocket errors
- Verify real-time updates work
References
Summary
The frontend WebSocket client sends a
session: 'cookie-auth'marker instead of the actual JWT token during WebSocket authentication. However, the backend WebSocket handler expects an actual JWT token in thetokenfield. This mismatch causes WebSocket authentication to fail.Vulnerability Details
src/services/api.ts(line ~210)backend/app/routers/websocket.py(line ~161-168)Current Behavior
Frontend (
src/services/api.ts):Backend (
backend/app/routers/websocket.py):Problem
{action: 'authenticate', session: 'cookie-auth'}auth_message.get("token")which isNoneRemediation Options
Option A: Backend accepts cookie-based auth (Recommended)
Modify
backend/app/routers/websocket.pyto check for HttpOnly cookie if no token in message:Option B: Frontend sends actual token in test mode
Modify
src/services/api.tsto send the actual token when available:Then backend needs to handle both cases.
Testing
References