How do you handle authentication in a WebSocket connection?
How to authenticate WebSocket connections: validate the handshake, use short-lived tickets, check Origin, and handle token expiry on long-lived sockets.
Expected Interview Answer
WebSocket authentication is done during the initial HTTP handshake using cookies, an Authorization header, or a short-lived token, because the browser WebSocket API cannot set custom headers, so most apps pass a token via cookie or a signed ticket and validate it before the upgrade completes.
Since the WebSocket protocol has no built-in auth, you authenticate the HTTP GET that requests the upgrade: verify a session cookie, a bearer token, or a signed ticket the client obtained from a REST endpoint. After the socket is open you should also authorize individual actions, and because a token can expire mid-connection you either close the socket on expiry or refresh via an application-level auth message. Never trust the Origin header alone; validate it to block cross-site hijacking but pair it with real credentials.
- Rejects unauthenticated clients before the connection is upgraded
- Reuses existing cookie or JWT session infrastructure
- Short-lived tickets avoid leaking long-lived tokens in URLs
- Per-message authorization limits what an open socket can do
- Origin checks mitigate cross-site WebSocket hijacking
AI Mentor Explanation
Think of entering the members' pavilion for a Test match. The guard checks your season pass at the single gate before you step inside; once through, you roam freely but stewards still check your pass before letting you into the players' area. WebSocket auth works the same way: credentials are verified at the handshake gate, and sensitive in-match actions get a second check even after you are seated.
Step-by-Step Explanation
Step 1
Authenticate the handshake
Validate the session cookie, bearer token, or signed ticket on the HTTP GET before accepting the upgrade.
Step 2
Validate Origin
Check the Origin header against an allowlist to defend against cross-site WebSocket hijacking.
Step 3
Prefer short-lived tickets
If headers are unavailable, have the client fetch a one-time ticket from REST and pass it as a query param.
Step 4
Authorize per action
After the socket opens, check permissions on each sensitive message rather than trusting the connection blindly.
Step 5
Handle token expiry
Close the socket or require an application-level re-auth message when the credential expires mid-connection.
What Interviewer Expects
- Understanding that auth happens at the HTTP handshake
- Awareness that the browser API cannot set custom headers
- Knowledge of the ticket or short-lived-token pattern
- Mention of Origin validation against hijacking
- Handling of token expiry on long-lived connections
Common Mistakes
- Assuming the WebSocket protocol has built-in authentication
- Putting long-lived JWTs in the URL where they get logged
- Trusting the Origin header as the only defense
- Never re-checking authorization after the socket opens
- Ignoring token expiry so a socket outlives its credential
Best Answer (HR Friendly)
“You prove who the user is when the connection is first set up, usually with a login cookie or a temporary token, before the socket is allowed to open. After that you keep checking permissions for sensitive actions and close the connection if the credential expires.”
Code Example
server.on('upgrade', (req, socket, head) => {
const ticket = new URL(req.url, 'http://x').searchParams.get('ticket');
const user = verifyTicket(ticket); // returns null if invalid or expired
if (!user || !allowedOrigins.has(req.headers.origin)) {
socket.write('HTTP/1.1 401 Unauthorized\r\n\r\n');
socket.destroy();
return;
}
wss.handleUpgrade(req, socket, head, (ws) => {
ws.user = user;
wss.emit('connection', ws, req);
});
});Follow-up Questions
- Why can't the browser WebSocket API set an Authorization header?
- How do you refresh an expiring token without dropping the socket?
- What is cross-site WebSocket hijacking and how do you prevent it?
- Why is a short-lived ticket safer than a long-lived JWT in the URL?
- How would you authorize individual messages after the socket is open?
MCQ Practice
1. At what point is a WebSocket connection typically authenticated?
Auth is performed on the HTTP GET that requests the upgrade, before the WebSocket connection is established.
2. Why is a short-lived ticket in the query string preferred over a long-lived JWT?
URLs land in server logs and proxies, so a one-time short-lived ticket limits the damage if it leaks.
3. What does validating the Origin header protect against?
Checking Origin against an allowlist blocks malicious pages from opening authenticated sockets on the user's behalf.
Flash Cards
Where does WebSocket auth happen? — During the HTTP upgrade handshake, before the connection is accepted.
Why use a ticket instead of a header? — The browser WebSocket API can't set custom headers, so a short-lived ticket is passed via cookie or query param.
What is cross-site WebSocket hijacking? — A malicious site opening an authenticated socket using the victim's cookies; mitigated by Origin checks plus real credentials.
How to handle token expiry? — Close the socket or require an app-level re-auth message when the credential expires mid-connection.