Implementing WebSocket Authentication

1. Understanding WebSocket Auth Challenges

ChallengeDetail
No custom headersBrowser cannot set headers on WS handshake (only cookies/sub-protocols/query)
Long-livedToken may expire mid-connection
CSWSHCross-Site WebSocket Hijacking — must check Origin

2. Implementing Handshake Authentication

Example: Verify in upgrade

wss.on("connection", async (ws, req) => {
  const origin = req.headers.origin;
  if (!ALLOWED.has(origin)) return ws.close(1008);
  const cookies = parse(req.headers.cookie || "");
  const user = await verifySession(cookies.sid);
  if (!user) return ws.close(1008);
  ws.user = user;
});

3. Using Query Parameters for Tokens

Warning: Tokens in URL leak to logs, browser history, referrer. Use only short-lived single-use tickets.
AspectDetail
Cookie sentBrowser includes session cookie automatically
Cross-originUse SameSite=None; Secure if cross-site
CSWSH protectionValidate Origin header strictly

5. Using Custom Headers (Non-Browser)

Native WS clients (Node, mobile) can set Authorization: Bearer ... on the HTTP upgrade. Not possible from browsers.

6. Implementing Token Refresh over WebSocket

StrategyDetail
Auth messageClient sends {type:"auth", token} over WS
Re-handshakeClose + reconnect with new token
GraceAllow current operations to complete

7. Handling Connection Authentication Failures

Close CodeMeaning
1008Policy violation (auth failed)
4001-4999App-defined (custom auth errors)
ClientDon't auto-reconnect on 4xxx without UX prompt

8. Implementing Heartbeat for Session Validation

Example: Ping with token check

setInterval(() => {
  if (Date.now() > ws.user.exp * 1000) return ws.close(4001, "token_expired");
  ws.ping();
}, 30_000);

9. Using Sub-Protocols for Auth

Example: Token via sub-protocol

// Browser
new WebSocket("wss://api.example/socket", ["bearer.token." + encodeURIComponent(jwt)]);

// Server reads Sec-WebSocket-Protocol header

10. Implementing Message-Level Authorization

PatternDetail
Per-message checkVerify permission for each action
Subscription authVerify on subscribe (channel access)
Rate limitPer-connection message throttle