Skip to content

WebSocket Handshake — Complete Guide

DodaTech Updated 2026-06-28 3 min read

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

  1. Implement subprotocol negotiation between a client and server.
  2. Add origin header validation to the server.
  3. Authenticate WebSocket connections using a token in the URL.
  4. Handle cookie-based session authentication.
  5. Challenge: Implement a custom authentication mechanism that validates a JWT during the handshake.

FAQ

What is a WebSocket subprotocol?

A subprotocol is a mutually agreed protocol layer on top of WebSocket. Examples include MQTT, WAMP, and JSON messaging formats.

How does origin validation prevent attacks?

Checking the Origin header ensures only your web application can open WebSocket connections, preventing Cross-Site WebSocket Hijacking.

Can I send headers during the handshake?

The client sends standard HTTP headers. The server sets response headers before the 101 status.

What happens if no matching subprotocol exists?

The server should not include Sec-WebSocket-Protocol in the response. The connection proceeds without a subprotocol.

Should I authenticate WebSocket connections?

Yes. Always authenticate WebSocket connections. Use tokens, cookies, or API keys passed during the handshake.

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