fix: send WS JWT as bare subprotocol name; CSSOM inline styles; open mgmt services on public zone
- websocket.js passes the raw JWT as the Sec-WebSocket-Protocol subprotocol (no 'Bearer ' prefix): subprotocol names must be valid RFC 6455 tokens, and the space in 'Bearer <token>' made the browser reject the constructor with a SyntaxError. - daemon accepts a JWT-shaped subprotocol plus the legacy 'Bearer <token>' form via _extract_ws_token; unit tests in tests/test_ws_auth.py. - vdom.js applies inline styles through el.style (CSSOM) instead of setAttribute, which the management-domain CSP (no 'unsafe-inline') blocks. - install.sh opens http/https/ssh on the public zone alongside WAN setup. - docs (hoover.md, security.md) updated to match.
This commit is contained in:
+1
-1
@@ -551,7 +551,7 @@ Link({ path: '/zones', class: 'active', children: ['Zones'] })
|
||||
|
||||
Start the WebSocket connection to the daemon at `ws://<host>/ws` (auto-detects `wss:` for HTTPS). Auto-reconnects with exponential backoff (max 15s).
|
||||
|
||||
The JWT is read from the auth model and sent in the WebSocket subprotocol header (`Bearer <token>`). With no token, no socket is created (the daemon 401s unauthenticated WS connections). After 3 consecutive close failures a token refresh is triggered through the auth model; reconnection branches on the model's token state (`getAuthToken()`), never on the refresh promise.
|
||||
The JWT is read from the auth model and sent as the WebSocket subprotocol name (`Sec-WebSocket-Protocol`) — the token is sent as-is, without a `Bearer ` prefix, because subprotocol names must be valid RFC 6455 tokens and a JWT (base64url + `.`) is one, while the space in `Bearer <token>` is not (the browser rejects the whole constructor with a SyntaxError). With no token, no socket is created (the daemon 401s unauthenticated WS connections). After 3 consecutive close failures a token refresh is triggered through the auth model; reconnection branches on the model's token state (`getAuthToken()`), never on the refresh promise.
|
||||
|
||||
### `disconnect()`
|
||||
|
||||
|
||||
+1
-1
@@ -104,7 +104,7 @@ Token theft protection:
|
||||
- Token blacklist prevents reuse after logout or password change
|
||||
- XSS mitigations: CSP headers, `X-XSS-Protection` header on management domain
|
||||
|
||||
**WebSocket session binding limitation**: WebSocket connections skip `session_id` validation. Browsers cannot send custom headers during the WebSocket handshake — the bundled nginx config passes the token via the `Sec-WebSocket-Protocol` subprotocol header (a custom nginx setup may instead inject it as `X-Auth-Token`). This means a stolen access token can be used to open WebSocket connections for the full 15-minute TTL without session verification. Short-lived TTL and management domain CSP headers mitigate this risk.
|
||||
**WebSocket session binding limitation**: WebSocket connections skip `session_id` validation. Browsers cannot send custom headers during the WebSocket handshake — the bundled client passes the raw JWT as the `Sec-WebSocket-Protocol` subprotocol name (a JWT is a valid RFC 6455 token; the `Bearer ` prefix is not, so it cannot be used) (a custom nginx setup may instead inject it as `X-Auth-Token`). This means a stolen access token can be used to open WebSocket connections for the full 15-minute TTL without session verification. Short-lived TTL and management domain CSP headers mitigate this risk.
|
||||
|
||||
### WebAuthn Security
|
||||
|
||||
|
||||
Reference in New Issue
Block a user