Skip to content
Language:en Author:Laborci Gergely
security

WebSocket Security and Troubleshooting

Objectives

By the end of the lesson, you can say what the Origin check protects and what it does not, how authentication and authorization should be handled on a persistent connection, and how connection faults can be distinguished and traced.

Why is it needed?

On a persistent connection, authentication is not a one-off exemption for all future messages. The connection may live longer than the token or the user's permission. The subscription, the incoming operations and the outgoing data must all be protected.

Handshake and Origin

According to RFC 6455, a server meant only for certain sites should check the Origin header, and if it is not the expected one, reject the connection with 403 Forbidden (section 10.2). This protects against cross-site WebSocket hijacking (CSWSH), where a script launched from another website opens a connection using the user's browser cookie. According to OWASP, Origin must be checked at every handshake against an explicit allowlist (not wildcards or substrings), and a SameSite setting on the session cookie is recommended. Origin is not a strong client identity: a non-browser client can send any value.

According to RFC 6455 (10.5), the protocol does not specify how the server authenticates the client during the handshake; any general HTTP mechanism (cookie, HTTP authentication, TLS authentication) can be used. The native browser constructor does not allow arbitrary header setting. OWASP's recommendation: the token should not go into the query part of the URL (it can end up in logs), but should be sent in the first message; until then no protected data should be sent, and if authentication fails or times out, the connection should be closed; on a long-lived connection the token must be rotated. Encryption: wss://; confidentiality and integrity are provided by TLS (RFC 6455, 10.6).

Authorization on every message

Knowing a channel name such as orders:customer-42 does not give access. The server checks the subscription based on the authenticated user and tenant, and filters the outgoing events too. According to OWASP, a WebSocket connection should not be treated as unlimited access: the permission of every operation must be checked, not only at connection time, which agrees with the principle of record-level authorization (6.7). On a change of permissions or the expiry of the session, access must be refreshed or the connection closed; OWASP suggests periodic re-checking.

Message limits

OWASP's recommendation: incoming messages are untrusted, so schema validation, message size limit, operation rate limit, limit on the number of connections (total and per user), idle timeout and Ping/Pong to clear dead connections are needed. A tiny message can also be expensive if it starts a thousand internal calls, so the limit looks at more than the byte count. An error response should not give detailed internal information.

Troubleshooting across layers

A connection fault can be a handshake rejection, a proxy timeout, an authentication error, a business rejection or a slow consumer; give these separate log codes. The connection identifier, the user's safe identifier and the operation identifier tie the events together. "Socket closed" is not enough: it must be known whether the operation was executed, whether the client fell behind, and what recovery path follows.

For HTTP and RPC calls the W3C Trace Context ties the call chain together: the traceparent header records the position of a request in the trace (version, trace-id, parent-id, flags), and the optional tracestate carries vendor-specific data. With messaging or a long-lived connection, the relation between producer and consumer can be marked with a propagated context or a trace link; not all background work is the continuation of a short-lived request. Metrics should not use the identifier of every connection or user as a label (unbounded cardinality); individual details should go into the log or the trace.

Characteristics

Aspect Security and diagnostics
Direction Handshake: client → server (authentication); afterwards both directions
Initiator The client the connection; either party the closing
Connection persistence Long: authentication can become outdated
Latency The extra cost of authentication and checking
Load Without limits a malicious client can exhaust resources
Fault tolerance Closing, re-authentication, handling expiry
When it fits A protected, authentic persistent channel
When it does not If authentication is regarded as a one-off login

Common misconceptions

Statement Clarification
"The Origin check replaces authentication." It protects against browser attacks only; it is not a strong identity.
"Knowing the channel name gives access." The server must check the permission.
"Authenticating once at connection is enough." Permission and token can expire.
"A token in the URL is convenient." It can end up in logs; the first message or a short-lived ticket is better.

In short

  • Origin must be checked against CSWSH, but it is not an identity.
  • Do not put the token into the URL; the first message or a short-lived ticket is better.
  • Check permission at every operation; limit message size, rate and connection count.
  • Error codes and Trace Context help traceability; do not use connection identifiers as metric labels.

Review questions

  1. Why does Origin not replace authentication?
  2. How does a revoked permission cease on a persistent connection?
  3. From what data would you separate a proxy error from a business rejection?

Learning resources

Prerequisites (2)

  • WebSocket
  • object-level authorization

Teaches (2)

  • cross-site WebSocket hijacking
  • distributed troubleshooting