Coverage for src / lexigram / contracts / auth / blacklist.py: 100%
7 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-19 05:41 +0800
« prev ^ index » next coverage.py v7.13.5, created at 2026-08-19 05:41 +0800
1"""Token blacklist protocol.
3Defines the contract for token blacklist implementations used to
4invalidate JWT tokens before their natural expiration time.
5"""
7from __future__ import annotations
9from typing import Protocol, runtime_checkable
12@runtime_checkable
13class TokenBlacklistProtocol(Protocol):
14 """Protocol for token blacklist implementations.
16 Implementations must support blacklisting tokens and checking whether
17 a token has been blacklisted. Concrete implementations may persist
18 entries in Redis (via CacheBackendProtocol) or keep them in-process for
19 environments that do not require distributed invalidation.
21 Example::
23 class RedisTokenBlacklist:
24 async def blacklist(self, token: str, ttl: int | None = None) -> None:
25 token_hash = hashlib.sha256(token.encode()).hexdigest()
26 await self._cache.set(f"jwt:blacklist:{token_hash}", "1", ttl=ttl)
28 async def is_blacklisted(self, token: str) -> bool:
29 token_hash = hashlib.sha256(token.encode()).hexdigest()
30 return await self._cache.exists(f"jwt:blacklist:{token_hash}")
31 """
33 async def blacklist(self, token: str, ttl: int | None = None) -> None:
34 """Add a token to the blacklist.
36 Args:
37 token: The raw token string to blacklist.
38 ttl: Time-to-live in seconds. If None the entry persists
39 indefinitely (only appropriate for in-memory stores).
40 """
41 ...
43 async def is_blacklisted(self, token: str) -> bool:
44 """Check whether a token is blacklisted.
46 Args:
47 token: The raw token string to check.
49 Returns:
50 ``True`` if the token is blacklisted, ``False`` otherwise.
51 """
52 ...
55__all__ = ["TokenBlacklistProtocol"]