tezvyn:

How to authenticate WebSocket connections using JWTs?

AI-drafted, machine-checkedSource: interviewintermediate
WHAT IT TESTS

WebSocket auth patterns and middleware understanding.

OUTLINE

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.