Move the edge credential out of the hello message
The `hello` frame carried a `token` field holding the edge JWT. It is gone: the token now travels in an `Authorization: Bearer` header on the WebSocket upgrade request. A token in the first frame means the backend has already accepted a socket, allocated state for it and run its JSON through this schema and a switch statement for a peer that has proved nothing. Every message type refused to act without a verified farm, so nothing could be done with such a connection - but "it cannot do anything" is a weaker guarantee than "it does not exist", and it needed a timeout to stop anyone holding sockets open for free. Verified at the handshake, an unauthenticated peer gets an HTTP 401 and no socket at all. The alternative of a `?token=` query parameter was rejected outright: a bearer credential in a URL lands in access logs, proxy logs and error breadcrumbs, which is exactly what continuum-proxy's hand-written `Debug` for `PrinterCommand` exists to avoid for presigned URLs. `Authorization` is the header every log tool already knows to redact. `farm_id` stays on the message even though the token carries the same claim. It is checked against the token rather than trusted, so sending it is how a misconfigured gateway gets caught instead of silently working against the wrong farm. A browser cannot set headers on a WebSocket, so a future user-facing socket cannot copy this exactly; its equivalent is the subprotocol field, `new WebSocket(url, ["bearer", token])`, which is also verified at the upgrade. Breaking change to the edge protocol, which is free right now: nothing is deployed. `npm run typecheck` and `npm run build` clean.
This commit is contained in:
@@ -166,7 +166,16 @@ export const EdgeClientMessageSchema = Type.Union([
|
||||
type: Type.Literal("hello"),
|
||||
gateway_id: Type.String(),
|
||||
farm_id: Type.String(),
|
||||
token: Type.String(),
|
||||
/*
|
||||
* No credential here, deliberately. The edge JWT travels in an
|
||||
* `Authorization: Bearer` header on the upgrade request and is verified
|
||||
* before the socket exists. A `token` field used to live on this
|
||||
* message; it was removed, because a token in the first frame means a
|
||||
* live socket and a parsed message for a peer that has proved nothing.
|
||||
*
|
||||
* `farm_id` is redundant with the token's own claim, and is checked
|
||||
* against it rather than trusted.
|
||||
*/
|
||||
/**
|
||||
* Where this gateway serves camera restreams, e.g.
|
||||
* `http://gateway.local:1984`. Omitted by a gateway with no cameras or
|
||||
|
||||
Reference in New Issue
Block a user