In this lesson, you will learn how to secure your WebSocket connections by validating user identity during the initial HTTP handshake before the socket is fully established.
Why the Handshake Matters
When a client initiates a WebSocket connection, it starts with a standard HTTP request containing an Upgrade header. If you wait until after the connection is upgraded to check for a valid session, an attacker could open thousands of unauthenticated sockets, exhausting your server resources (a Denial of Service vulnerability). By securing the handshake, we reject unauthorized users before they consume any persistent memory or socket slots on our server.
Implementing Authentication during Handshake
The most common approach in Node.js is to verify a JWT or session cookie before the upgrade event is finalized. If you are using the ws library, you can intercept the HTTP request during the server's handleUpgrade process.
Here is a simplified example of how to check a session cookie before allowing the upgrade:
const http = require('http');
const { WebSocketServer } = require('ws');
const server = http.createServer();
const wss = new WebSocketServer({ noServer: true });
server.on('upgrade', (request, socket, head) => {
// 1. Extract session or token from headers/cookies
const isAuthenticated = authenticateUser(request);
if (!isAuthenticated) {
// 2. Reject the connection immediately
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
// 3. Only proceed if authenticated
wss.handleUpgrade(request, socket, head, (ws) => {
wss.emit('connection', ws, request);
});
});
By checking the identity here, we treat the WebSocket connection like any other protected API endpoint. The logic inside authenticateUser should mirror your existing session validation strategy (e.g., verifying a signed JWT or checking your session store). Once handleUpgrade is called, you know your socket is reserved only for a verified user, keeping your infrastructure safe from anonymous spikes and unauthorized traffic.
Key Takeaway: Always perform identity verification during the initial HTTP handshake to prevent unauthenticated users from establishing persistent, resource-consuming socket connections.