In the WebSocket protocol, why can a browser page not set an HTTP Authorization request header on the upgrade?
answer
- the page never builds the request
- URL and subprotocol list only
- ordinary GET, then the 101
- cookies ride automatically, tokens do not
- a non-browser client has no such limit
basics
~20 sThe upgrade is an ordinary HTTP GET issued by the browser itself, and the page's socket API accepts only a URL and a list of subprotocol names. There is no place to add a request field, so no Authorization.
solid answer
~40 sA WebSocket connection starts as an HTTP/1.1 `GET` carrying `Upgrade: websocket`, `Connection: Upgrade`, `Sec-WebSocket-Key` and `Sec-WebSocket-Version: 13`, answered by `101 Switching Protocols`. Nothing in RFC 6455 forbids an `Authorization` field on that request — the restriction is in the browser: the client API a page gets accepts a URL and an optional subprotocol list and nothing else, so the page never builds the request and cannot add fields to it. What still travels automatically is a cookie scoped to the target origin. That leaves four practical routes for a credential: the cookie, a token in the URL query string, a token smuggled as a second subprotocol value, or a short-lived ticket redeemed on the upgrade. A non-browser client writes the request itself and is under none of this.
code
http · 13 linesGET /cabinet/socket HTTP/1.1
Host: console.example.org
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
Sec-WebSocket-Version: 13
Origin: https://console.example.org
Cookie: cabinet_session=8f2c1d...
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=go deeper
Recall that a WebSocket starts life as an HTTP GET with Upgrade and Connection fields, and that a page can only influence the URL and the subprotocol list. That is enough to explain why the header is missing.
Explain that the restriction is a client API limitation rather than a protocol rule, and walk the four routes a credential can take instead, naming what each costs on the wire.
Demonstrate that the answer depends on the client kind, and that the check happens once at the handshake — so the identity a connection carries all shift is whatever the upgrade established.
Frame it as a fleet decision: whether one endpoint serves both page and service clients with two credential routes, or two endpoints each accept one, and what that costs in review surface.
## The upgrade is an ordinary HTTP request A WebSocket connection does not begin as a socket. It begins as an HTTP/1.1 `GET` that asks the server to change protocols. That request carries `Upgrade: websocket`, `Connection: Upgrade`, a client-generated `Sec-WebSocket-Key` and `Sec-WebSocket-Version: 13`; the server answers `101 Switching Protocols` with a `Sec-WebSocket-Accept` digest, and from that moment the same TCP connection carries frames instead of HTTP messages. Because it is an ordinary HTTP request, it can carry ordinary HTTP request fields. **RFC 6455 places no restriction on an `Authorization` field on the upgrade.** The limitation that every team runs into is on the client side, and it applies to exactly one kind of client. ## What a page's client API actually accepts The socket API a browser gives a page takes two things: - the **URL** — scheme, authority, path and query string, all under your control; - an optional **list of subprotocol names**, which the browser puts in `Sec-WebSocket-Protocol`. That is the entire input surface. The page does not construct the request, so it cannot add, remove or edit a single field on it. Cookies are attached by the browser according to the cookie's own attributes, not by your code. So the practical question is never "which header do I use" — it is "which of the two inputs I control can carry a credential, and what does that cost." ## The routes a credential can actually take | Route | Who can use it | What it costs | |---|---|---| | Session **cookie** | a browser page | sent automatically, including on an upgrade started by a page you do not control, so cross-site protection becomes load-bearing; the cookie's own attributes decide whether it travels at all | | **Token in the query string** | any client | lands in the server's access log, every intermediary's access log, browser history, and any copy of that URL — the most common credential leak on this protocol | | **Token as a second `Sec-WebSocket-Protocol` value** | any client | abuses a negotiation field; the server must select exactly one value to echo and it must not be the token | | **Short-lived single-use ticket** in the query string | any client | one extra authenticated request before the upgrade; the shape that survives review | | **Credential in the first frame** after the socket opens | any client | the server has already accepted an unauthenticated connection and must time it out if no credential arrives | None of these is free, and a candidate who names the trade-off rather than a favourite is the one answering the question. ## A non-browser client is under no such limitation A server-to-server client, a command-line client or a native application writes the upgrade request itself. It sets `Authorization` exactly as it would on any other HTTP request, and the whole problem disappears. This is why the honest answer to "how do you authenticate a WebSocket" begins with a question back: **which client?** A console running in a browser and a background service opening the same endpoint have different answers, and an interviewer listening for that distinction hears it immediately. It also means a server that accepts only `Authorization` is not wrong — it is simply unusable from a page, which may be exactly the intent for an internal endpoint. ## What the check is worth Whatever route you choose, the authentication happens **once**, on the request that opens the connection. If it succeeds the server completes the handshake; if it fails the server refuses the upgrade with an ordinary HTTP error response instead of the `101`, and no socket ever exists. There is no second credential exchange defined by the protocol, and no per-frame credential: once the connection is up, everything the server knows about who is on the other end is whatever it recorded at the handshake and attached to the connection. On a console that dispenses controlled substances, that single check is the entire identity story for a connection that may stay open all shift — which is why the same leaf goes on to ask what happens when the credential behind it expires. ## What an interviewer is listening for 1. That the upgrade **is** HTTP, so HTTP mechanisms are in play at all. 2. That the missing header is a **client API** limitation, not a protocol rule. 3. That the answer **differs by client kind**. 4. That the cookie is not a neutral default — it is a choice with a cross-site consequence.
- If the protocol allows an Authorization field on the upgrade, when is it actually the right choice?Whenever the client is not a browser page. A service, a native application or a command-line client builds the upgrade request itself and can set any request field on it, so it authenticates the handshake exactly as it would any other HTTP request — no ticket endpoint, no token in the URL, no cookie. Restricting an endpoint to that route is a reasonable way to say "not callable from a page".
- What does the server know about the caller once the socket is open?Only what it recorded during the handshake and bound to the connection. The protocol defines no second credential exchange and no per-frame identity, so every frame that arrives is attributed to the principal established at open. Anything finer — per-message authorization, a principal that can change — is the application's own invention layered on top.
- Can the page authenticate after the socket opens instead?Yes, by sending the credential in the first application frame, and some designs do. The cost is that the server has already accepted a connection from an unauthenticated peer: it must hold that socket in an unauthenticated state, refuse every other message until a valid credential arrives, and close it on a short timer if one never does.
saying these in an interview costs you the question
- Says RFC 6455 forbids an Authorization field on the upgrade request
- Thinks the WebSocket upgrade is not an HTTP request at all
- Believes every client is limited the way a browser page is
- Assumes wss encryption removes the need to authenticate the handshake
- Treats an in-band first-message credential as costing nothing