Types and protocols¶
Runtime-checkable Protocol definitions and type aliases used across transports, strategies, and user models.
DbSessionDependencyKey is the public type alias for LitestarAuthConfig.db_session_dependency_key.
It is an Annotated[str, ...] contract: values must be valid non-keyword Python identifiers because
Litestar matches dependency keys to callable parameter names. The default is "db_session".
RoleCapableUserProtocol is the dedicated public typing surface for user objects that expose normalized flat roles membership. Use that protocol directly instead of treating an arbitrary roles attribute as sufficient.
That protocol describes the library boundary rather than a storage implementation detail. Bundled
SQLAlchemy models now persist roles through relational role / user_role tables, but managers,
schemas, and guards still exchange one normalized flat roles collection. This remains flat role
membership, not a full RBAC permission model.
Which protocol should my user model implement?¶
Pick the narrowest protocol that covers the features you enable. If a guard or TOTP flow needs attributes your model does not expose, authentication may succeed while authorization fails with a generic permission error—so align the model with Guards and TOTP usage up front.
| If you use… | Implement |
|---|---|
Basic authentication only (strategies resolve request.user by id) |
UserProtocol or UserProtocolStrict — id |
is_active, is_verified guards |
GuardedUserProtocol — is_active, is_verified |
is_superuser, has_any_role / has_all_roles guards |
RoleCapableUserProtocol — roles |
| TOTP enrollment, verification, or 2FA flows | TotpUserProtocol — email, totp_secret |
Use UserProtocol when code needs isinstance(user, UserProtocol) at runtime. Use
UserProtocolStrict for static-only annotations and type-variable bounds. The strict variant avoids
the @runtime_checkable tradeoff: runtime protocol checks are convenient but only validate the
runtime-visible shape of the protocol and carry extra overhead.
Config inference and dependency-key typing¶
Construct LitestarAuthConfig directly. For strict typing, spell both generic parameters as
LitestarAuthConfig[User, UUID](...) so the configured user and ID types stay explicit.
The db_session_dependency_key parameter is typed as DbSessionDependencyKey, so the annotation
documents the same identifier rule enforced at runtime. This complete example type-checks as
LitestarAuthConfig[User, UUID]:
from dataclasses import dataclass
from typing import assert_type
from uuid import UUID
from litestar_auth import LitestarAuthConfig
from litestar_auth.types import DbSessionDependencyKey
from litestar_auth.manager import BaseUserManager
from litestar_auth.types import UserProtocolStrict
@dataclass(slots=True)
class User:
id: UUID
email: str
class UserManager(BaseUserManager[User, UUID]):
pass
def needs_static_user_contract(user: UserProtocolStrict[UUID]) -> UUID:
return user.id
dependency_key: DbSessionDependencyKey = "db_session"
config = LitestarAuthConfig[User, UUID](
user_model=User,
user_manager_class=UserManager,
db_session_dependency_key=dependency_key,
)
assert_type(config, LitestarAuthConfig[User, UUID])
Example: account state and roles together¶
A single model often needs GuardedUserProtocol and RoleCapableUserProtocol so both
account-state and role guards can run:
from collections.abc import Sequence
from dataclasses import dataclass
@dataclass(slots=True)
class StaffUser:
"""Satisfies GuardedUserProtocol and RoleCapableUserProtocol."""
id: int
is_active: bool
is_verified: bool
roles: Sequence[str]
Add TOTP fields when you enable 2FA; see TotpUserProtocol in the generated API below.
litestar_auth.types
¶
Shared typing primitives and authentication protocols.
Protocol selection (abbreviated)¶
Implement the narrowest protocol that matches the features you use:
| Feature area | Required protocol |
|---|---|
Basic authentication (identity in strategies, User typing) |
UserProtocol — id |
is_active, is_verified guards |
GuardedUserProtocol — account state booleans |
is_superuser, has_any_role, has_all_roles guards |
RoleCapableUserProtocol — flat roles |
| TOTP enrollment / verification | TotpUserProtocol — email, totp_secret |
UserProtocol remains @runtime_checkable so runtime guard code can use isinstance(...).
Use UserProtocolStrict for static-typing-only contracts where no runtime check is needed; avoiding
@runtime_checkable keeps the protocol's stricter static intent clear and avoids protocol runtime-check overhead.
The full decision table, guard cross-links, and a multi-protocol model example are in
docs/api/types.md (API → Types in the built docs).
ContextualStrategyProtocol
¶
Bases: StrategyProtocol[UP, ID], Protocol[UP, ID]
Protocol for strategies that expose custom request authentication context.
read_token_with_context(token, user_manager)
async
¶
GuardedUserProtocol
¶
RoleCapableUserProtocol
¶
Bases: UserProtocol[ID], Protocol[ID]
Protocol for user models that expose normalized flat role membership.
StrategyProtocol
¶
TotpUserProtocol
¶
TransportProtocol
¶
UserProtocol
¶
Bases: UserProtocolStrict[ID], Protocol[ID]
Runtime-checkable protocol for user models handled by the library.
This variant supports isinstance(...) checks, which are convenient at runtime but slower and less precise
than static protocol validation. Use :class:UserProtocolStrict when runtime checks are unnecessary.
UserProtocolStrict
¶
Bases: Protocol[ID]
Static-only protocol for user models handled by the library.
Prefer this variant for annotations and TypeVar bounds that do not need isinstance(...) checks.