Source code for rath.server.auth

"""Pluggable Agent Server authentication."""

from __future__ import annotations

import hashlib
import hmac
from typing import Protocol, runtime_checkable

from rath.security import SecurityContext

__all__ = ["AuthProvider", "StaticTokenAuth"]


[docs] @runtime_checkable class AuthProvider(Protocol):
[docs] async def authenticate(
self, authorization: str | None ) -> SecurityContext | None: ...
[docs] class StaticTokenAuth: """Reference bearer-token provider for self-hosted deployments and tests.""" def __init__(self, tokens: dict[str, SecurityContext]) -> None: if not tokens: raise ValueError("at least one authentication token is required") self._tokens = { hashlib.sha256(token.encode()).digest(): context for token, context in tokens.items() }
[docs] async def authenticate(self, authorization: str | None) -> SecurityContext | None: if not authorization or not authorization.startswith("Bearer "): return None supplied = hashlib.sha256( authorization.removeprefix("Bearer ").strip().encode() ).digest() for expected, context in self._tokens.items(): if hmac.compare_digest(supplied, expected): return context return None