WebSocket Security — Complete Guide
In this tutorial, you will learn about WebSocket Securityet" >}} Security. We cover key concepts, practical examples, and best practices to help you master this topic.
WebSocket security requires protection at multiple levels: transport (TLS), handshake (origin validation), authentication (token verification), and message level (validation, Rate Limiting, size limits). Unlike HTTP, there are no built-in CSRF protections.
What You'll Learn
- Cross-Site WebSocket Hijacking (CSWSH) prevention
- Origin header validation
- Input sanitization and validation
- Rate limiting and message size limits
- TLS and authentication enforcement
Why It Matters
WebSocket bypasses standard web security mechanisms like CSRF tokens. Without origin validation, any website can open a WebSocket connection to your API using the user's existing session.
Real-World Use
Slack validates Origin headers. Discord uses token authentication in the WebSocket handshake. Trading platforms enforce strict input validation and rate limiting on WebSocket endpoints.
flowchart TD
Request[WebSocket Request] --> TLS{TLS Enabled?}
TLS -->|No| Reject[Reject Connection]
TLS -->|Yes| Origin{Origin Valid?}
Origin -->|Invalid| Reject
Origin -->|Valid| Auth{Authenticated?}
Auth -->|No| Reject
Auth -->|Yes| Rate{Rate Limit OK?}
Rate -->|Exceeded| Reject
Rate -->|OK| Accept[Accept Connection]
Accept --> Validate[Validate Messages]
Teacher Mindset
Treat every WebSocket connection as potentially malicious. Validate the origin. Require authentication. Set rate limits and message size limits. Sanitize all incoming data. Never trust the client.
Code Examples
// Example 1: Origin validation
const WebSocket = require('ws');
const allowedOrigins = ['https://app.example.com', 'https://admin.example.com'];
const server = new WebSocket.Server({ port: 8080 });
server.on('connection', (ws, req) => {
const origin = req.headers.origin;
if (!origin || !allowedOrigins.includes(origin)) {
console.warn(`Blocked connection from origin: ${origin}`);
ws.close(1008, 'Origin not allowed');
return;
}
console.log(`Allowed connection from: ${origin}`);
});
// Example 2: Input validation and sanitization
const server = new WebSocket.Server({ port: 8080 });
server.on('connection', (ws) => {
ws.on('message', (data) => {
try {
const message = JSON.parse(data);
// Validate structure
if (!message.type || !message.payload) {
ws.send(JSON.stringify({ error: 'Invalid message format' }));
return;
}
// Validate type
const allowedTypes = ['chat', 'join', 'leave'];
if (!allowedTypes.includes(message.type)) {
ws.send(JSON.stringify({ error: 'Unknown message type' }));
return;
}
// Sanitize text content
if (message.payload.text) {
message.payload.text = sanitizeHtml(message.payload.text);
}
// Check message size
const size = Buffer.byteLength(JSON.stringify(message), 'utf8');
if (size > 10000) {
ws.send(JSON.stringify({ error: 'Message too large' }));
return;
}
// Process valid message
handleMessage(ws, message);
} catch (err) {
ws.send(JSON.stringify({ error: 'Invalid JSON' }));
}
});
});
// Example 3: WebSocket rate limiting
const rateLimits = new Map();
function wsRateLimit(ws, req) {
const clientIp = req.socket.remoteAddress;
const now = Date.now();
const windowMs = 10000;
const maxRequests = 20;
if (!rateLimits.has(clientIp)) {
rateLimits.set(clientIp, []);
}
const timestamps = rateLimits.get(clientIp);
const recent = timestamps.filter(t => now - t < windowMs);
recent.push(now);
rateLimits.set(clientIp, recent);
if (recent.length > maxRequests) {
ws.close(1008, 'Rate limit exceeded');
return false;
}
ws.on('close', () => {
rateLimits.delete(clientIp);
});
return true;
}
server.on('connection', (ws, req) => {
if (!wsRateLimit(ws, req)) return;
// Normal connection handling
});
Common Mistakes
- Not validating the Origin header, leaving the API vulnerable to CSWSH
- Sending sensitive data (tokens, user data) over unencrypted ws://
- Not sanitizing HTML in chat messages (XSS via WebSocket)
- Allowing unlimited message sizes (DoS risk)
- Trusting client-provided user IDs without server-side validation
Practice
- Add origin validation to your WebSocket server.
- Implement JSON message validation with allowed types.
- Add server-side rate limiting per IP address.
- Set message size limits and reject oversized messages.
- Challenge: Implement a comprehensive security middleware that checks origin, rate limit, message size, and message schema.
FAQ
Mini Project
Add four security layers to your WebSocket server: TLS enforcement (wss:// only), origin validation against an allowed list, token-based authentication during handshake, and per-connection rate limiting (30 messages per 30 seconds).
What's Next
Next, you will learn about WebSocket deployment strategies for production environments.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro