"""Where a websocket's credential comes from, and how it stays out of the URL. A client that can set headers sends `Authorization: Bearer` on the handshake: the worker and the SDK. A browser cannot, so it trades its token for a ticket over an authenticated REST call and brings the ticket instead. A ticket is good once, for thirty seconds, so the URL every proxy logs is worth nothing after. The engine is one process, so the tickets live in its memory: the tunnel connector, which serves the live socket inline, redeems them from the same place. """ from __future__ import annotations import secrets import threading from collections.abc import Mapping from time import monotonic #: How long a ticket waits to be used: the length of one connect. TICKET_TTL_S = 30.0 _tickets: dict[str, tuple[str, float]] = {} _lock = threading.Lock() def issue_ticket(token: str) -> str: """A one-time ticket standing in for *token*.""" ticket = secrets.token_urlsafe(32) now = monotonic() with _lock: # Swept here rather than on a timer: issuing is what fills the table. for stale in [key for key, (_, due) in _tickets.items() if due <= now]: del _tickets[stale] _tickets[ticket] = (token, now + TICKET_TTL_S) return ticket def redeem_ticket(ticket: str) -> str: """The token a ticket stands for, once; empty if it is unknown or stale.""" with _lock: entry = _tickets.pop(ticket, None) if entry is None or entry[1] <= monotonic(): return "" return entry[0] def socket_token(headers: Mapping[str, str], ticket: str = "", token: str = "") -> str: """The credential a handshake carries: a header, then a ticket, then a token. `token` is the query parameter clients sent before the other two existed. It is read for one more release so an engine can be upgraded before its workers; remove it after that (see NOTEPAD). """ header = headers.get("authorization") or "" if header.lower().startswith("bearer "): return header[7:] if ticket: return redeem_ticket(ticket) return token