WebSocket Handshake — Complete Guide
In this tutorial, you will learn about Websocket Handshake. We cover key concepts, practical examples, and best practices to help you master this topic.
The WebSocket handshake is the HTTP upgrade that establishes a WebSocket connection. Beyond the basic upgrade, it supports subprotocol negotiation, extension negotiation, and origin-based security checks.
What You'll Learn
- Subprotocol negotiation with Sec-WebSocket-Protocol
- Extension negotiation with Sec-WebSocket-Extensions
- Origin header validation for security
- Authentication during the handshake
- Cookie-based session handling
Why It Matters
The handshake is the place to negotiate protocol details and enforce security. Choosing the right subprotocol simplifies message routing. Origin validation prevents cross-site WebSocket hijacking.
Real-World Use
Socket.IO uses the subprotocol header for transport negotiation. Slack validates origin headers to prevent CSWSH attacks. Financial APIs use subprotocols to indicate message encoding formats.
flowchart LR
Client[Client] -->|Request| Server[Server]
Request --> SubProto[Sec-WebSocket-Protocol: chat, json]
Request --> Origin[Origin: https://app.example.com]
Request --> Cookie[Cookie: session=abc123]
Server -->|Response| Client
Response --> Selected[Sec-WebSocket-Protocol: json]
Response --> Accept[Sec-WebSocket-Accept: ...]
Teacher Mindset
The handshake is your only chance to negotiate protocol details. After the 101 response, all communication is frame-based. Use subprotocols to agree on message formats and security parameters.
Code Examples
// Example 1: Client with subprotocol negotiation
const socket = new WebSocket('wss://api.example.com/chat', ['json', 'msgpack']);
socket.onopen = () => {
console.log('Negotiated protocol:', socket.protocol);
// Sends 'json' or 'msgpack' depending on server selection
};
// Example 2: Server with subprotocol selection
const WebSocket = require('ws');
const server = new WebSocket.Server({
port: 8080,
handleProtocols: (protocols, request) => {
// Prefer msgpack over json
if (protocols.has('msgpack')) return 'msgpack';
if (protocols.has('json')) return 'json';
return false; // Reject if no matching protocol
}
});
server.on('connection', (ws, req) => {
console.log('Protocol:', ws.protocol);
// Origin check
const origin = req.headers.origin;
if (!isAllowedOrigin(origin)) {
ws.close(1008, 'Origin not allowed');
return;
}
console.log('Connection from:', origin);
});
// Example 3: Authentication via handshake
const server = new WebSocket.Server({ port: 8080 });
server.on('connection', (ws, req) => {
// Extract token from query string or cookie
const url = new URL(req.url, 'http://localhost');
const token = url.searchParams.get('token');
const sessionCookie = req.headers.cookie;
if (!token && !sessionCookie) {
ws.close(4001, 'Authentication required');
return;
}
const user = verifyToken(token || sessionCookie);
if (!user) {
ws.close(4001, 'Invalid token');
return;
}
ws.user = user; // Attach user to connection
console.log('Authenticated user:', user.name);
});
Common Mistakes
- Not validating the Origin header in the server, leaving it open to CSWSH attacks
- Closing the connection with non-standard status codes that confuse clients
- Not handling the case where no matching subprotocol is available
- Adding authentication logic after the handshake instead of during it
- Ignoring Cookie headers for session-based WebSocket authentication
Practice
- Implement subprotocol negotiation between a client and server.
- Add origin header validation to the server.
- Authenticate WebSocket connections using a token in the URL.
- Handle cookie-based session authentication.
- Challenge: Implement a custom authentication mechanism that validates a JWT during the handshake.
FAQ
Mini Project
Build a WebSocket server that: validates Origin headers, negotiates between json and msgpack subprotocols, authenticates via token query parameter, and assigns the user context to the connection.
What's Next
Next, you will learn about WebSocket frames: text, binary, close, ping, and pong frames.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro