Coverage for src/lexigram/graphql/subscriptions/auth.py: 50%
24 statements
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 04:37 +0800
« prev ^ index » next coverage.py v7.15.4, created at 2026-08-25 04:37 +0800
1"""Subscription authentication hooks.
3Provides connection-level authentication for WebSocket subscriptions.
4"""
6from __future__ import annotations
8from collections.abc import Awaitable, Callable
9from typing import Any
11from lexigram.graphql.exceptions import AuthenticationError
13# Type for connection auth hook
14ConnectionAuthHook = Callable[[dict[str, Any]], Awaitable[bool]]
17class SubscriptionAuth:
18 """Handles authentication for WebSocket subscriptions.
20 Provides hooks for validating connection tokens during connection_init.
21 """
23 def __init__(
24 self,
25 on_auth: ConnectionAuthHook | None = None,
26 ):
27 """Initialize the subscription auth handler.
29 Args:
30 on_auth: Optional async callback to validate auth payload.
31 Should return True if authentication succeeds.
32 """
33 self._on_auth = on_auth
35 async def authenticate(self, payload: dict[str, Any]) -> bool:
36 """Authenticate a connection_init payload.
38 Args:
39 payload: The payload from the connection_init message.
41 Returns:
42 True if authentication succeeds.
44 Raises:
45 AuthenticationError: If authentication fails.
46 """
47 if self._on_auth is None:
48 # No auth hook - allow all connections
49 return True
51 try:
52 result = await self._on_auth(payload)
53 if not result:
54 raise AuthenticationError("Authentication failed")
55 return result
56 except AuthenticationError:
57 raise
58 except (TypeError, ValueError, RuntimeError) as e:
59 raise AuthenticationError(f"Authentication error: {e}") from e
61 def set_auth_hook(self, hook: ConnectionAuthHook) -> None:
62 """Set the authentication hook.
64 Args:
65 hook: Async callback to validate auth payload.
66 """
67 self._on_auth = hook
70# Default auth instance
71default_auth = SubscriptionAuth()
74__all__ = ["ConnectionAuthHook", "SubscriptionAuth", "default_auth"]