Script Valley
WebSockets & Real-Time Applications
Building a WebSocket Server with Node.jsLesson 3.4

How to authenticate WebSocket connections

JWT in query string, Authorization header on upgrade, cookie-based auth, verifying token on connection, rejecting unauthenticated clients, per-client auth state, token refresh with WebSocket

Authenticate at Connection Time

WebSocket upgrades are regular HTTP requests. Authenticate before accepting the connection. The cleanest approach for browser clients is a JWT in the query string (not ideal for sensitive tokens, but practical):

const jwt = require('jsonwebtoken'); const SECRET = process.env.JWT_SECRET; wss.on('connection', (ws, req) => { const url = new URL(req.url, 'http://localhost'); const token = url.searchParams.get('token'); let user; try { user = jwt.verify(token, SECRET); } catch (err) { ws.close(4001, 'Invalid token'); return; } ws.userId = user.id; ws.send(JSON.stringify({ type: 'authenticated', userId: user.id })); });

Using the HTTP Server for Pre-Auth

A more secure approach: authenticate with a REST endpoint first, receive a short-lived one-time token (OTT), pass the OTT on the WebSocket URL. The server validates and immediately marks it used. This avoids long-lived tokens in URLs appearing in server logs. Reject any connection where token validation fails — close with code 4001 immediately, before any application data is sent.

Up next

How to handle WebSocket server errors and unexpected disconnects

Sign in to track progress