"""In-memory token store for WebSocket authentication. Tokens are short-lived (24h) and stored in memory. Since this is a single-device appliance with typically one user, persistence is not needed. Tokens are cleaned up lazily on create/validate calls. """ import secrets from datetime import datetime, timezone, timedelta _tokens: dict[str, dict] = {} TOKEN_TTL_HOURS = 24 def create_token(username: str) -> str: """Create a new auth token for the given username. Args: username: The authenticated username Returns: URL-safe token string """ token = secrets.token_urlsafe(32) _tokens[token] = { "username": username, "expires_at": datetime.now(timezone.utc) + timedelta(hours=TOKEN_TTL_HOURS), } _cleanup_expired() return token def validate_token(token: str) -> str | None: """Validate a token and return the associated username. Args: token: The token to validate Returns: Username if valid, None if invalid or expired """ entry = _tokens.get(token) if not entry: return None if datetime.now(timezone.utc) > entry["expires_at"]: del _tokens[token] return None return entry["username"] def _cleanup_expired() -> None: """Remove expired tokens.""" now = datetime.now(timezone.utc) expired = [t for t, e in _tokens.items() if now > e["expires_at"]] for t in expired: del _tokens[t]