Authentication in WebSocket connections helps verify who is connecting. It keeps your app safe by allowing only trusted users to communicate.
Authentication in WebSocket connections in Express
const WebSocket = require('ws'); const wss = new WebSocket.Server({ noServer: true }); server.on('upgrade', (request, socket, head) => { // Extract token from request headers or URL const token = extractToken(request); if (isValidToken(token)) { wss.handleUpgrade(request, socket, head, (ws) => { wss.emit('connection', ws, request); }); } else { socket.destroy(); } });
Authentication usually happens during the HTTP upgrade request before WebSocket connection is established.
You can extract tokens from headers, cookies, or URL query parameters.
sec-websocket-protocol header to pass a token for authentication.const token = request.headers['sec-websocket-protocol']; if (token === 'my-secret-token') { // Accept connection }
const url = new URL(request.url, 'http://localhost'); const token = url.searchParams.get('token'); if (token === 'valid-token') { // Accept connection }
This example shows a simple WebSocket server using Express's HTTP server. It checks a token from the URL query during the upgrade request. If the token is correct, it accepts the connection and sends a welcome message. Otherwise, it rejects the connection.
const http = require('http'); const express = require('express'); const WebSocket = require('ws'); const app = express(); const server = http.createServer(app); const wss = new WebSocket.Server({ noServer: true }); function isValidToken(token) { return token === 'secret123'; } server.on('upgrade', (request, socket, head) => { const url = new URL(request.url, 'http://localhost'); const token = url.searchParams.get('token'); if (!isValidToken(token)) { socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n'); socket.destroy(); return; } wss.handleUpgrade(request, socket, head, (ws) => { wss.emit('connection', ws, request); }); }); wss.on('connection', (ws) => { ws.send('Welcome! You are authenticated.'); ws.on('message', (message) => { ws.send(`You said: ${message}`); }); }); server.listen(8080, () => { console.log('Server listening on http://localhost:8080'); });
Always validate tokens securely, for example by checking against a database or using JWT verification.
Do not trust tokens sent from the client without verification.
Use secure WebSocket (wss://) in production to protect data in transit.
Authentication happens during the HTTP upgrade request before WebSocket connection starts.
Tokens can be sent via headers or URL query parameters for verification.
Reject unauthorized connections by closing the socket early.
Practice
Solution
Step 1: Understand WebSocket handshake
The WebSocket connection starts with an HTTP upgrade request from client to server.Step 2: Identify when authentication fits
Authentication must happen during this upgrade request to allow or deny the connection before it opens.Final Answer:
During the HTTP upgrade request before the WebSocket connection is established -> Option AQuick Check:
Authentication = HTTP upgrade request [OK]
- Trying to authenticate after WebSocket connection opens
- Assuming authentication is unnecessary for WebSocket
- Authenticating only on first message instead of handshake
Solution
Step 1: Review token sending methods during upgrade
Tokens can be sent in the URL query string or headers during the HTTP upgrade request.Step 2: Identify valid option
Sending the token as a URL query parameter is a common and valid method to authenticate during upgrade.Final Answer:
Send the token as a URL query parameter in the WebSocket URL -> Option BQuick Check:
Token in URL query = valid during upgrade [OK]
- Sending token only after connection opens
- Using cookies after connection instead of during upgrade
- Sending token in separate HTTP requests unrelated to upgrade
server.on('upgrade', (req, socket, head) => {
const token = new URL(req.url, 'http://localhost').searchParams.get('token');
if (token !== 'secret') {
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
wss.handleUpgrade(req, socket, head, ws => {
wss.emit('connection', ws, req);
});
});
What happens if the token is incorrect?Solution
Step 1: Analyze token check and socket handling
If the token is not 'secret', the code writes a 401 Unauthorized response and destroys the socket immediately.Step 2: Understand socket.destroy effect
Destroying the socket closes the connection before WebSocket handshake completes, rejecting the client.Final Answer:
The socket connection is closed immediately with 401 Unauthorized -> Option DQuick Check:
Invalid token = socket closed with 401 [OK]
- Assuming connection is accepted but blocked later
- Thinking server crashes on invalid token
- Ignoring socket.destroy effect
server.on('upgrade', (req, socket, head) => {
const token = req.headers['sec-websocket-protocol'];
if (!token || token !== 'valid-token') {
socket.end();
return;
}
wss.handleUpgrade(req, socket, head, ws => {
wss.emit('connection', ws, req);
});
});
What is the main issue with this authentication approach?Solution
Step 1: Understand 'sec-websocket-protocol' header usage
This header is meant for subprotocol negotiation, not for authentication tokens.Step 2: Recognize handshake impact
Misusing this header can cause handshake failure or client rejection because clients expect specific values here.Final Answer:
Using 'sec-websocket-protocol' header for token is incorrect and may cause handshake failure -> Option AQuick Check:
Wrong header for token breaks handshake [OK]
- Assuming any header can carry token safely
- Ignoring WebSocket protocol header purpose
- Confusing socket.end() and socket.destroy() effects
server.on('upgrade', (req, socket, head) => {
// Extract token
const token = req.headers['authorization']?.split(' ')[1];
// Verify token
if (!token || token !== 'my-secret-token') {
// Reject connection
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
// Accept connection
wss.handleUpgrade(req, socket, head, ws => {
wss.emit('connection', ws, req);
});
});Solution
Step 1: Check token extraction method
The code extracts the token from the Authorization header using standard Bearer token format.Step 2: Verify rejection method
If token is invalid, it writes a 401 Unauthorized response and destroys the socket before upgrade completes, properly rejecting connection.Step 3: Confirm acceptance flow
If token is valid, it calls handleUpgrade and emits connection event to accept the WebSocket connection.Final Answer:
This approach correctly extracts token from Authorization header and rejects unauthorized connections during upgrade -> Option CQuick Check:
Authorization header + socket.destroy() = secure upgrade [OK]
- Using cookies instead of headers for token during upgrade
- Calling socket.destroy() after upgrade instead of before
- Not sending 401 response before closing socket
Ready to prove it?
Pass the test and this pattern moves unknown
