diff --git a/docs/websocket.md b/docs/websocket.md index 0141d10..0e6e42c 100644 --- a/docs/websocket.md +++ b/docs/websocket.md @@ -19,10 +19,42 @@ **No-auth mode** (`NAVI_AUTH_ENABLED=false`): neither cookies nor tokens are required. Every WebSocket connection is treated as the local `anonymous` admin user. -> **Security note**: `?api_token` is visible in server access logs. For log-sensitive deployments, future versions may support sending `{type: "auth", api_token: "..."}` as the first WebSocket message after connect instead. +> **Security note**: `?api_token` is visible in server access logs. On connect the server immediately sends either `session_sync` (no active run) or begins the reconnect flow (active run detected). +### Future work: WebSocket auth message (deferred) + +Status: **not implemented** — recorded here for later. Tracked as task #248. + +The current headless auth path puts the API token in the connection URL: +`?api_token=nav_...`. Query strings are written to reverse-proxy / uvicorn +access logs, so a long-lived API token leaks into log files — anyone who can +read the logs (or a leaked log) gets the token's full access. + +Planned hardening for log-sensitive deployments: accept the token as the first +WebSocket frame instead of a query parameter. + +```json +{"type": "auth", "api_token": "nav_aB3xYz9W..."} +``` + +Sketch: +- On connect, the server holds the socket in an unauthenticated state and sends + nothing except an optional `auth_required` prompt. +- The client must send `{type: "auth", api_token}` as its first message within a + short timeout (e.g. 5s); messages received before auth are buffered and + replayed once the user is resolved. +- The server resolves the user (`_resolve_user_from_api_token`), then proceeds + with the existing access-check / `session_sync` / reconnect flow. +- Any non-`auth` message before auth (or timeout) → close `4003`. `?api_token` + query param stays as a fallback for backward compatibility. + +Scope is limited to headless clients with auth enabled. Browser clients use the +`navi_auth_session` cookie (no URL token) and local `navi_code` runs in no-auth +mode — neither is affected. Only remote headless clients (CLI/TUI/automation +against an auth-enabled server) benefit. + --- ## Messages: client → server