Implementing Authentication

1. Passing Tokens in URL

Example: Query token

const ws = new WebSocket(`wss://api.example.com/ws?token=${encodeURIComponent(jwt)}`);
ProsCons
Simple, works in browserLogged in server access logs
No first-message danceCached in browser history
Warning: Use short-lived tokens (≤ 60s) and rotate; never long-lived secrets in URLs.

2. Using Custom Headers

ContextSupported
Browser WebSocketNo (only cookies / subprotocol)
Node wsYes (headers option)
React NativePartial

Example: Subprotocol token (browser workaround)

const ws = new WebSocket("wss://x/", [`bearer.${jwt}`, "chat.v2"]);
// server reads Sec-WebSocket-Protocol and accepts

3. Sending Authentication Message

Example: Auth-first protocol

ws.addEventListener("open", () => ws.send(JSON.stringify({ "type":"auth","token":jwt })));
ws.addEventListener("message", (e) => {
  const m = JSON.parse(e.data);
  if (m.type === "auth.ok") onReady();
  else if (m.type === "auth.fail") ws.close(4401, "auth");
});
StepServer Behavior
Accept connectAllow unauthenticated open
Await authTimer (e.g. 5s) to close
ValidateReply ok/fail
PromoteMark connection authenticated

4. Validating JWT Tokens

CheckDetail
SignatureVerify with public key (RS/ES) or secret (HS)
expNot expired (with clock skew)
iss / audMatch expected
nbfNot yet valid?
RevocationCheck denylist / use short TTL
// browser sends cookies on same-origin upgrades automatically
const ws = new WebSocket("wss://api.example.com/ws");
// server reads req.headers.cookie
AttributeRecommendation
HttpOnlyYes (prevent XSS theft)
SecureYes (HTTPS/WSS only)
SameSiteLax or Strict
Cross-origin WSValidate Origin header

6. Implementing OAuth Flow

OAuth + WebSocket

  1. Frontend gets access token (Auth Code + PKCE)
  2. Request short-lived "WS ticket" from API
  3. Open WS with ?ticket=...
  4. Server validates ticket once, opens connection
  5. Refresh access token; rotate ticket on reconnect

7. Handling Session Management

ConcernAction
Multi-deviceAllow N sessions per user
Session bindWS holds session ref
RevokeClose all sockets on logout

8. Implementing Token Refresh

Example: Refresh before expiry

function scheduleRefresh(exp) {
  const skew = 30_000;
  const delay = exp * 1000 - Date.now() - skew;
  setTimeout(async () => {
    const fresh = await refreshAccessToken();
    ws.send(JSON.stringify({ "type":"auth.refresh","token":fresh.access }));
    scheduleRefresh(fresh.exp);
  }, Math.max(0, delay));
}

9. Closing Unauthorized Connections

CodeReason
4401Auth required / token expired
4403Forbidden (no permission)
4408Auth timeout (no auth message)
4429Auth rate-limited

10. Implementing Multi-Factor Authentication

StepDetail
Primary authPassword / OAuth before WS
MFA challengeTOTP/WebAuthn over HTTP
Issue WS ticketAfter MFA success
Step-up authRe-MFA before sensitive ops