How to authenticate WebSocket connections using JWTs?
WebSocket auth patterns and middleware understanding.
client sends JWT on connection, server validates via middleware, socket is attached to user.
THE WEBSOCKET HANDSHAKE
Unlike REST requests, WebSocket connections don't have standard HTTP headers for auth. Socket.IO allows the client to send authentication data during the handshake via a query parameter or a custom header. The typical pattern is to pass the JWT: io('http://localhost:3000', { auth: { token: jwtToken } }).
MIDDLEWARE VALIDATION
Socket.IO middleware intercepts every connection before the 'connection' event fires. You register middleware with io.use(). Inside, receive the socket and next callback. Extract the token, validate it synchronously or asynchronously, then call next() to allow the connection or throw an error to reject it.
VALIDATION FUNCTION
The server-side validation mirrors REST JWT logic: decode the token with jwt.verify(), check the signature, validate expiry. If valid, attach the decoded payload to the socket: socket.userId = decoded.userId. If invalid, throw new Error('Authentication error'). Middleware errors automatically reject the connection with a 'connect_error' event on the client.
FLOW END-TO-END
Client prepares JWT, initiates connection with auth parameter. Server middleware receives the socket before 'connection' event. Middleware extracts token from socket.handshake.auth.token, calls jwt.verify(). If valid, decodes userId and attaches to socket.userId. Middleware calls next(), allowing the connection. The 'connection' event fires, now socket.userId is available for use. If invalid, middleware throws, 'connect_error' fires on client, connection is rejected.
MULTIPLE SOCKETS PER USER
When a user connects from a phone and a laptop, each gets a different socket object. Attach the same userId to both. You can now find all sockets for a user: io.sockets.sockets.forEach(socket => { if (socket.userId === userId) { /* handle */ } }). This allows per-user broadcasts.
REFRESH TOKEN CONSIDERATIONS
If your JWT expires quickly, WebSocket connections become invalid mid-session. Consider either using longer-lived JWTs for real-time, or implementing a token-refresh mechanism. Socket.IO allows middleware to reject and trigger reconnection, giving the client a chance to fetch a fresh token.
Read the original → socket.io
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.