Authentication
The gateway is the single public entry point for the LIS platform. Every caller authenticates the same two ways: a shared API key and a per-user identity. HTTP requests carry them as headers; WebSocket connections carry them as query parameters. Authentication is implemented in gateway_service/api/dependencies.py.
HTTP authentication
REST endpoints are guarded by the get_current_user dependency. It performs two checks:
- API key — the
X-Api-Keyheader is compared against the configured key (GATEWAY_API_TOKEN). A mismatch or missing key returns401. - User identity — the
X-User-IDheader must be present and a valid UUID. A missing header returns400; a malformed value also returns400.
Send both headers on every user-scoped request:
X-Api-Key: <api_key>
X-User-ID: <user_uuid>
X-User-ID is a trusted UUID: the gateway has no users table and does not verify the identity beyond its format. Session and memory records are scoped to this value.
The API key check is fail-open. When GATEWAY_API_TOKEN is empty (the default), no key is required and X-Api-Key is ignored. Set the token in production to enforce it.
Missing or malformed X-User-ID produces 400, not 401 — the request is rejected as malformed rather than unauthenticated.
See HTTP Endpoints for the full list of REST routes. All of them mount under the /api_lis prefix.
WebSocket authentication
WebSocket routes cannot send request headers on the handshake, so credentials are passed as query parameters. The router accepts the socket first, then runs ws_auth; on failure the socket is closed with a specific close code rather than rejected outright.
ws_auth validates, in order:
api_key— compared againstGATEWAY_API_TOKEN(fail-open when unset). Mismatch closes with4001.user_id— must be present (4001if missing) and a valid UUID (4003if malformed).
Base query parameters for every WebSocket endpoint:
?user_id=<user_uuid>&api_key=<api_key>
Individual endpoints require additional identifiers:
| Endpoint | Extra identifier | Location |
|---|---|---|
/api_lis/sessions/{session_id}/message | session_id | URL path |
/api_lis/voiceover | session_id | query parameter (required) |
/api_lis/transcribe | language_hint | query parameter (optional) |
For the message endpoint, after auth the client must send a UserPreferences JSON object as its first frame; an invalid session_id or a first frame that is not valid UserPreferences closes the socket with 4003. For the voiceover endpoint, a missing or non-UUID session_id query parameter closes with 4003.
See WebSocket Protocol for the message envelope and event details.
Close codes
When a WebSocket connection fails authentication or resolution, the gateway closes the already-accepted socket with one of these application close codes:
| Code | Reason | When |
|---|---|---|
4001 | Auth failure | Invalid/missing api_key, or missing user_id |
4003 | Malformed IDs | Non-UUID user_id or session_id, or an invalid first frame |
4004 | Session not found | Session (or avatar) not found or not owned by the caller |
4001 and 4003 are raised by ws_auth and the connection router before any upstream connection. 4004 is raised later, during relay, once session ownership is resolved against the database.
Auth dependencies
| Dependency | Transport | Purpose |
|---|---|---|
get_current_user | HTTP | Validates X-Api-Key, then requires a valid X-User-ID UUID. Guards every REST endpoint. |
require_api_key | HTTP | Validates X-Api-Key only. Defined but not attached to any route. |
ws_auth | WebSocket | Validates ?api_key, then ?user_id from the connection query parameters. |
All three share the internal _check_api_key helper, which enforces the key only when GATEWAY_API_TOKEN is non-empty.