DEV Community

andreagomez
andreagomez

Posted on

Authenticating WebSocket connections at the edge

Authenticating WebSocket connections at the edge

A WebSocket session begins as an ordinary HTTP request and stops being one after the server answers with 101 Switching Protocols. Authentication middleware, reverse proxies and web application firewalls get one chance to inspect that request. After the upgrade they see a long-lived TCP connection carrying frames they usually do not parse. Teams that protect REST endpoints carefully often leave the socket path to whatever the framework does by default.

What the handshake carries

RFC 6455 defines the opening handshake, including Upgrade: websocket, Sec-WebSocket-Key and Sec-WebSocket-Version: 13. Because the handshake is an HTTP request, it carries cookies and an Authorization header when the client chooses to send them. That is where a session check belongs.
Browsers also send an Origin header, and it matters for one specific attack. Browsers do not apply the same-origin policy to WebSocket connections the way they do to fetch and XMLHttpRequest, so a page on one origin can open a socket to another origin and the browser attaches the target's cookies. Validating Origin on the server is the control that stops that cross-site WebSocket hijacking pattern, as documented in the OWASP WebSocket security guidance. Origin is a browser-supplied value, so it is useful for that purpose and useless as authentication, because a scripted client can send any value it likes.

Tokens in the URL

Passing a bearer token in the query string is common because the browser WebSocket API does not allow custom headers. It also writes the credential into access logs, proxy logs and anything else that records request lines. Issuing a short-lived ticket from the application and redeeming it during the handshake keeps the long-lived credential out of URLs. The Sec-WebSocket-Protocol header is sometimes used to carry a token; some proxies log it, so the same caution applies.

Authorisation is per message

A connection that authenticated once can stay open while permissions change. Subscription protocols need a decision at subscribe time for each topic, and a re-check when a role is revoked. A socket opened by an employee who leaves in the afternoon is still authenticated in the evening unless the application closes it.

Operational checks worth running

  • Confirm the proxy forwards Upgrade and Connection. nginx needs proxy_http_version 1.1 plus explicit header settings.
  • Log the identity and the authorisation decision when the connection opens, and log the close reason when a credential expires.
  • Test what happens when a session is revoked while a socket is open.
  • Confirm gateway and WAF policy covers the socket path and not only /api/.

References

  • RFC 6455, The WebSocket Protocol
  • OWASP WebSocket Security Cheat Sheet
  • OWASP, Cross-Site WebSocket Hijacking
  • nginx documentation, WebSocket proxying

Top comments (0)