Strategies¶
Token strategies validate or issue credentials and pair with transports inside an AuthenticationBackend (see Backends: transports and strategies). Three concrete implementations ship with litestar-auth:
-
JWTStrategyissues and verifies stateless signed JWTs with your configured signing keys. Library-issued access tokens include JOSEtyp=JWT; decode rejects tokens with a missing or unexpectedtypheader before the normal signed validation. This header check is defense-in-depth against token-class confusion and does not replace signature, algorithm allowlist, audience, issuer, or required-claim validation. Use this strategy when you want bearer or cookie flows without storing each access token in a database or Redis—scaling and rotation are typically driven by expiry and refresh semantics rather than per-token rows. UseJWTStrategyConfig(...)when you want the signing, validation, revocation, lifetime, and session-fingerprint settings carried as one typed object. The default session-fingerprint HMAC key is HKDF-SHA256-derived from the signing secret with a JWT fingerprint domain; tokens minted by older versions with raw-secret fingerprints are intentionally rejected and users must re-login once after deployment. -
DatabaseTokenStrategystores opaque tokens in your application database (hashed at rest). Use it when you need durable revocation, per-token metadata, refresh-session/device listing, or audit trails aligned with your ORM models. UseDatabaseTokenStrategyConfig(...)when the session, token models, token hash secret, access lifetime, refresh lifetime, and token-size settings should travel together. -
RedisTokenStrategykeeps opaque token state in Redis with TTL-backed keys and a per-user token index. Use it when you want fast invalidation and shared token state across app instances without adding DB round-trips for every validation.invalidate_all_tokens(...)atomically bumps a per-user invalidation epoch and deletes indexed token and TOTP step-up marker keys. Token reads validate that epoch, so orphaned token keys missing from the per-user index are rejected on their next use after invalidation without a keyspace scan. The per-user index key hashes the serialized user id before adding it to the Redis key, so custom id values cannot inject key delimiters or reshape the namespace. You can construct it withRedisTokenStrategyConfig(...)when you want the Redis client, hash secret, TTL, key prefix, token byte count, and optional subject decoder carried as one typed settings object. -
ApiKeyStrategyverifies user-owned API keys against aBaseApiKeyStore. Configure it withApiKeyStrategyConfigor equivalent keyword arguments. Bearer keys compare the presented secret with the stored HMAC digest. Signing-required keys use the encrypted stored secret to verifyLSA1-HMAC-SHA256normalized request signatures, validateX-Auth-Datewithinsigning_skew_seconds, and reject replayedX-Auth-Noncevalues through anApiKeyNonceStore. Successful reads returnApiKeyAuthenticationResultwith the resolved user andApiKeyContext; middleware exposes that context asrequest.auth.
For plugin-oriented setup, DatabaseTokenAuthConfig on LitestarAuthConfig is the direct shortcut for wiring opaque database-backed tokens (hash secret, optional backend naming, and related compatibility flags) without hand-assembling the strategy and related pieces in isolation. Full wiring for the preset, route flags, and related options is covered in Backends; ORM mixins, token tables, and SQLAlchemyUserDatabase contracts are covered in User and manager.
Refresh-session management support¶
The session/device HTTP API is backed by a strategy protocol rather than by controller-side database
queries. DatabaseTokenStrategy implements that protocol and can:
- list the authenticated user's active, non-expired refresh sessions;
- revoke one current-user session by public
session_id; - revoke all other current-user sessions, preserving the current session when the current refresh credential can be identified;
- identify a public
session_idfrom a raw refresh token by hashing the supplied value and comparing it with stored digests; - record consumed refresh-token digests during rotation and revoke the whole refresh-session chain when a consumed token is presented again.
JWTStrategy and RedisTokenStrategy do not currently provide the session/device dashboard
contract. If plugin-owned session/device routes are enabled against an unsupported strategy, the
route returns 400 with SESSION_MANAGEMENT_UNSUPPORTED; it does not synthesize empty session data.
The API never returns raw tokens, access tokens, refresh tokens, stored token digests, or keyed token
digests.
litestar_auth.authentication.strategy
¶
Issue, validate, rotate, and revoke tokens (JWT, database, or Redis).
Strategies pair with :mod:litestar_auth.authentication.transport implementations
inside :class:~litestar_auth.authentication.backend.AuthenticationBackend.
DatabaseTokenModels is the explicit contract for DatabaseTokenStrategy when you swap in
mixin-composed token ORM classes. The explicit bundled-token bootstrap helper lives at
litestar_auth.models.import_token_orm_models().
ApiKeyContext(key_id, scopes, prefix_env, scope_subset_check=True, scope_authority=None)
dataclass
¶
Authentication context exposed as request.auth for API-key requests.
ApiKeyNonceStore
¶
Bases: Protocol
Persistence contract for API-key signing nonces.
mark_used(*, key_id, nonce, ttl_seconds)
async
¶
ApiKeyNonceStoreResult(stored, rejected_as_replay=False)
dataclass
¶
Outcome of recording a request-signing nonce.
ApiKeyStrategy(*, config=None, **options)
¶
Bases: Strategy[UP, ID]
Verify API-key credentials against indexed persisted key rows.
Initialize the API-key strategy.
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
ConfigurationError
|
If |
Source code in litestar_auth/authentication/strategy/api_key.py
classify_failure_code(token)
async
¶
Return the most specific API-key authentication failure code for token.
Source code in litestar_auth/authentication/strategy/api_key.py
classify_failure_reason(token)
async
¶
Return the most specific API-key authentication failure reason for token.
Source code in litestar_auth/authentication/strategy/api_key.py
destroy_token(token, user)
async
¶
Do nothing because API-key revocation is handled by API-key management flows.
read_token(token, user_manager)
async
¶
Resolve a user from an API-key token.
Returns:
| Type | Description |
|---|---|
UP | None
|
Resolved user, or |
Source code in litestar_auth/authentication/strategy/api_key.py
read_token_attempt(token, user_manager)
async
¶
Resolve an API-key request and preserve the failed reason when rejected.
Returns:
| Type | Description |
|---|---|
ApiKeyAuthenticationAttempt[UP]
|
Successful authentication result, or |
Source code in litestar_auth/authentication/strategy/api_key.py
read_token_with_context(token, user_manager)
async
¶
Resolve a user and API-key context from a canonical API-key token.
Returns:
| Type | Description |
|---|---|
ApiKeyAuthenticationResult[UP] | None
|
Resolved user and API-key context, or |
Source code in litestar_auth/authentication/strategy/api_key.py
write_token(user)
async
¶
Reject login-token issuance because API keys are manager-issued credentials.
Raises:
| Type | Description |
|---|---|
TokenError
|
Always, because API keys are not login-flow tokens. |
Source code in litestar_auth/authentication/strategy/api_key.py
ApiKeyStrategyConfig(api_key_store, api_key_hash_secret, prefix_env=None, prefix=API_KEY_PREFIX, scope_subset_check=True, scope_authority=None, signing_skew_seconds=300, nonce_store=None, secret_encryption_keyring=None, unsafe_testing=False)
dataclass
¶
Configuration for :class:ApiKeyStrategy.
ContextualStrategy
¶
Bases: Protocol
Protocol for strategies that return custom request auth context.
read_token_with_context(token, user_manager)
async
¶
Resolve a user plus strategy-specific authentication context.
DatabaseTokenModels(access_token_model=AccessToken, refresh_token_model=RefreshToken, consumed_refresh_token_digest_model=RefreshTokenConsumedDigest)
dataclass
¶
Explicit token ORM contract for DatabaseTokenStrategy.
The supplied access-token model must expose mapped token, created_at, user_id, and user
attributes compatible with the persistence operations performed by the DB token strategy. The supplied
refresh-token model must also expose session_id, last_used_at, and client_metadata so
DB-backed refresh sessions have a non-sensitive public session identifier and bounded client metadata.
The consumed refresh-token digest model must expose mapped token_digest, session_id, and
consumed_at attributes for replay detection. Defaults preserve the bundled token-table behavior.
__post_init__()
¶
Validate the supplied token-model classes eagerly.
Source code in litestar_auth/authentication/strategy/db_models.py
DatabaseTokenStrategy(*, config=None, **options)
¶
Bases: _DatabaseRefreshSessionMixin[UP, ID], Strategy[UP, ID], RefreshableStrategy[UP, ID]
Stateful strategy that persists opaque tokens in the database.
Initialize the strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
DatabaseTokenStrategyConfig | None
|
Database-token strategy configuration. |
None
|
**options
|
Unpack[DatabaseTokenStrategyOptions]
|
Individual database-token strategy settings. Do not combine
with |
{}
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
ConfigurationError
|
When |
Source code in litestar_auth/authentication/strategy/db.py
cleanup_expired_tokens(session)
async
¶
Delete expired access and refresh tokens for the configured TTLs.
Returns:
| Type | Description |
|---|---|
int
|
Total number of deleted access-token and refresh-token rows. |
Source code in litestar_auth/authentication/strategy/db.py
destroy_token(token, user)
async
¶
Delete a persisted token.
Source code in litestar_auth/authentication/strategy/db.py
invalidate_all_tokens(user)
async
¶
Delete all persisted access and refresh tokens for the given user.
Source code in litestar_auth/authentication/strategy/db.py
read_token(token, user_manager)
async
¶
Resolve a user from an opaque database token.
Returns:
| Type | Description |
|---|---|
UP | None
|
Related user when the token exists and is not expired, otherwise |
Source code in litestar_auth/authentication/strategy/db.py
with_session(session)
¶
Return a copy of the strategy bound to the provided async session.
Source code in litestar_auth/authentication/strategy/db.py
write_refresh_token(user)
async
¶
Persist and return a new opaque refresh token for the user.
Returns:
| Type | Description |
|---|---|
str
|
Newly created opaque refresh-token string. |
Source code in litestar_auth/authentication/strategy/db.py
write_token(user)
async
¶
Persist and return a new opaque token for the user.
Returns:
| Type | Description |
|---|---|
str
|
Newly created opaque token string. |
Source code in litestar_auth/authentication/strategy/db.py
DatabaseTokenStrategyConfig(session, token_hash_secret, token_models=None, max_age=DEFAULT_MAX_AGE, refresh_max_age=DEFAULT_REFRESH_MAX_AGE, token_bytes=DEFAULT_TOKEN_BYTES, unsafe_testing=False)
dataclass
¶
Configuration for :class:DatabaseTokenStrategy.
InMemoryApiKeyNonceStore(*, clock=time.monotonic, max_entries=50000)
¶
Async-safe process-local API-key signing nonce store.
Initialize an empty nonce cache.
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in litestar_auth/authentication/strategy/_api_key_nonce_store.py
is_shared_across_workers
property
¶
In-memory state is process-local.
mark_used(*, key_id, nonce, ttl_seconds)
async
¶
Record a nonce until TTL expiry, rejecting replays fail-closed.
Returns:
| Type | Description |
|---|---|
ApiKeyNonceStoreResult
|
Stored/replay outcome for the nonce insert. |
Source code in litestar_auth/authentication/strategy/_api_key_nonce_store.py
JWTContext(organization=None)
dataclass
¶
Authentication context exposed as request.auth for JWT requests.
JWTStrategy(*, config=None, **options)
¶
Bases: Strategy[UP, ID]
Stateless strategy that stores user identifiers inside JWTs.
JWT access tokens issued by this strategy are designed to be short-lived
and stateless. Revocation uses the configured denylist keyed by the jti
claim so individual tokens can be explicitly revoked before expiration when
:meth:destroy_token is called.
Production deployments should pass a shared denylist store such as
:class:RedisJWTDenylistStore. Single-process tests, development apps, and
consciously single-process deployments can opt into :class:InMemoryJWTDenylistStore with
allow_inmemory_denylist=True. Inspect :attr:revocation_posture to
determine whether a concrete strategy instance uses process-local or durable
shared-store revocation.
Initialize the JWT strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
JWTStrategyConfig[UP, ID] | None
|
JWT strategy configuration. |
None
|
**options
|
Unpack[JWTStrategyOptions[UP, ID]]
|
Individual JWT strategy settings. Do not combine with
|
{}
|
Source code in litestar_auth/authentication/strategy/jwt.py
revocation_is_durable
property
¶
Return whether token revocation is backed by a shared store.
revocation_posture
property
¶
Return the explicit revocation durability contract for this strategy.
destroy_token(token, user)
async
¶
Revoke the given token by adding its jti to the configured denylist.
Tokens without a jti claim, or tokens that fail to decode, are ignored.
Raises:
| Type | Description |
|---|---|
TokenError
|
When the denylist refuses a new revocation (for example, the
compatibility in-memory store is at |
Source code in litestar_auth/authentication/strategy/jwt.py
read_token(token, user_manager)
async
¶
Decode a JWT token and load its user.
Returns:
| Type | Description |
|---|---|
UP | None
|
The matching user, or |
Source code in litestar_auth/authentication/strategy/jwt.py
read_token_with_context(token, user_manager)
async
¶
Decode a JWT token and expose verified organization claim context.
Returns:
| Type | Description |
|---|---|
JWTAuthenticationResult[UP] | None
|
Resolved user plus optional organization context, or |
JWTAuthenticationResult[UP] | None
|
the token does not authenticate. |
Source code in litestar_auth/authentication/strategy/jwt.py
write_token(user)
async
¶
Generate an organization-free JWT token for the provided user.
Returns:
| Type | Description |
|---|---|
str
|
The encoded JWT token string. |
write_token_for_organization(user, organization)
async
¶
Generate a JWT token bound to a verified active organization.
Callers must verify that user is a member of organization before
invoking this method. The strategy only normalizes and signs the
organization claim; it performs no membership lookup itself.
Returns:
| Type | Description |
|---|---|
str
|
The encoded JWT token string carrying the normalized organization claim. |
Source code in litestar_auth/authentication/strategy/jwt.py
JWTStrategyConfig(secret, verify_key=None, algorithm=DEFAULT_ALGORITHM, lifetime=DEFAULT_LIFETIME, subject_decoder=None, issuer=None, denylist_store=None, allow_inmemory_denylist=False, session_fingerprint_getter=None, session_fingerprint_claim='sfp')
dataclass
¶
Configuration for :class:JWTStrategy.
RedisApiKeyNonceStore(*, redis, key_prefix=DEFAULT_API_KEY_NONCE_PREFIX)
¶
Redis-backed API-key signing nonce store.
Store the Redis client and key namespace.
Source code in litestar_auth/authentication/strategy/_api_key_nonce_store.py
is_shared_across_workers
property
¶
Redis state is shared across workers using the same server.
mark_used(*, key_id, nonce, ttl_seconds)
async
¶
Atomically record a nonce with SET NX PX.
Returns:
| Type | Description |
|---|---|
ApiKeyNonceStoreResult
|
Stored/replay outcome for the nonce insert. |
Source code in litestar_auth/authentication/strategy/_api_key_nonce_store.py
RedisApiKeyNonceStoreClient
¶
Bases: RedisConditionalSetClient, Protocol
Minimal Redis client for API-key signing nonce storage.
RedisTokenStrategy(*, config=None, **options)
¶
Bases: Strategy[UP, ID]
Stateful strategy that stores opaque tokens in Redis with TTL.
Initialize the strategy.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
config
|
RedisTokenStrategyConfig[ID] | None
|
Redis strategy configuration. |
None
|
**options
|
Unpack[RedisTokenStrategyOptions[ID]]
|
Individual Redis strategy settings. Do not combine with
|
{}
|
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
ConfigurationError
|
When |
Source code in litestar_auth/authentication/strategy/redis.py
destroy_token(token, user)
async
¶
Delete a persisted Redis token.
Source code in litestar_auth/authentication/strategy/redis.py
has_recent_totp_verification(user, session_id)
async
¶
Return whether a Redis-backed session has a live TOTP step-up marker.
Source code in litestar_auth/authentication/strategy/redis.py
invalidate_all_tokens(user)
async
¶
Delete all Redis-backed tokens associated with the given user.
This bumps a per-user invalidation epoch before deleting indexed token and step-up marker keys, so out-of-index tokens are rejected on their next read without requiring a keyspace scan.
Source code in litestar_auth/authentication/strategy/redis.py
issue_totp_stepup(user, session_id, *, ttl_seconds)
async
¶
Store a short-lived TOTP step-up marker for a Redis-backed session.
Source code in litestar_auth/authentication/strategy/redis.py
read_token(token, user_manager)
async
¶
Resolve a user from a Redis-backed token.
Returns:
| Type | Description |
|---|---|
UP | None
|
The resolved user when the token exists and decodes successfully, |
UP | None
|
otherwise |
Source code in litestar_auth/authentication/strategy/redis.py
write_token(user)
async
¶
Persist a new opaque token in Redis and return it.
Returns:
| Type | Description |
|---|---|
str
|
Newly created opaque token string. |
Source code in litestar_auth/authentication/strategy/redis.py
RedisTokenStrategyConfig(redis, token_hash_secret, lifetime=DEFAULT_LIFETIME, token_bytes=DEFAULT_TOKEN_BYTES, key_prefix=DEFAULT_KEY_PREFIX, subject_decoder=None)
dataclass
¶
Configuration for :class:RedisTokenStrategy.
RefreshableStrategy
¶
Bases: Protocol
Protocol for strategies that support refresh-token rotation.
Note
Refresh tokens are intentionally modeled as a separate lifecycle artifact from
access tokens. In particular, Strategy.destroy_token() only targets the access
token used for request authentication; refresh-token invalidation (if any) is
managed by the refresh strategy itself.
rotate_refresh_token(refresh_token, user_manager)
async
¶
Consume a refresh token and return the user plus a rotated replacement.