Skip to content

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 UserProtocolStrictid
is_active, is_verified guards GuardedUserProtocolis_active, is_verified
is_superuser, has_any_role / has_all_roles guards RoleCapableUserProtocolroles
TOTP enrollment, verification, or 2FA flows TotpUserProtocolemail, 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) UserProtocolid
is_active, is_verified guards GuardedUserProtocol — account state booleans
is_superuser, has_any_role, has_all_roles guards RoleCapableUserProtocol — flat roles
TOTP enrollment / verification TotpUserProtocolemail, 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

Resolve a user plus strategy-specific request auth context.

Source code in litestar_auth/types.py
async def read_token_with_context(self, token: str | None, user_manager: object) -> object | None:
    """Resolve a user plus strategy-specific request auth context."""

GuardedUserProtocol

Bases: UserProtocol[ID], Protocol[ID]

Protocol for user models that support account-state guards.

RoleCapableUserProtocol

Bases: UserProtocol[ID], Protocol[ID]

Protocol for user models that expose normalized flat role membership.

StrategyProtocol

Bases: Protocol[UP, ID]

Protocol describing how auth tokens map to users.

destroy_token(token, user) async

Invalidate a token for strategies that keep server-side state.

Source code in litestar_auth/types.py
async def destroy_token(self, token: str, user: UP) -> None:
    """Invalidate a token for strategies that keep server-side state."""

read_token(token, user_manager) async

Resolve a user from a transport token.

Source code in litestar_auth/types.py
async def read_token(self, token: str | None, user_manager: object) -> UP | None:
    """Resolve a user from a transport token."""

write_token(user) async

Create a token for a given user.

Source code in litestar_auth/types.py
async def write_token(self, user: UP) -> str:
    """Create a token for a given user."""

TotpUserProtocol

Bases: UserProtocol[ID], Protocol[ID]

Protocol for user models that support TOTP 2FA.

TransportProtocol

Bases: Protocol

Protocol describing how auth tokens move in and out of requests.

read_token(connection) async

Extract a login token from an incoming connection.

Source code in litestar_auth/types.py
async def read_token(self, connection: ASGIConnection[Any, Any, Any, Any]) -> str | None:
    """Extract a login token from an incoming connection."""

set_login_token(response, token)

Persist a login token on an outgoing response.

Source code in litestar_auth/types.py
def set_login_token(self, response: Response[Any], token: str) -> Response[Any]:
    """Persist a login token on an outgoing response."""

set_logout(response)

Clear any transport-specific authentication state.

Source code in litestar_auth/types.py
def set_logout(self, response: Response[Any]) -> Response[Any]:
    """Clear any transport-specific authentication state."""

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.