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
Why does Origin not replace authentication?
How does a revoked permission cease on a persistent connection?
From what data would you separate a proxy error from a business rejection?
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
Originheader, and if it is not the expected one, reject the connection with403 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 aSameSitesetting 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-42does 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
traceparentheader records the position of a request in the trace (version,trace-id,parent-id, flags), and the optionaltracestatecarries 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
Common misconceptions
In short
Review questions
Learning resources