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. -
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(...)deletes only tokens present in that per-user index; orphaned keys from older deployments that never wrote the index are left to expire by their Redis TTL instead of being discovered by 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.
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
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_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)
dataclass
¶
Explicit access-token and refresh-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.
Defaults preserve the bundled AccessToken / RefreshToken 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: 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
has_recent_totp_verification(user, session_id)
async
¶
Return whether a DB-backed refresh session has a live TOTP step-up marker.
Source code in litestar_auth/authentication/strategy/db.py
identify_refresh_session(user, refresh_token)
async
¶
Return the public refresh-session id for refresh_token when it belongs to user.
Returns:
| Type | Description |
|---|---|
str | None
|
Public refresh-session id, or |
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
issue_totp_stepup(user, session_id, *, ttl_seconds)
async
¶
Store a short-lived TOTP step-up marker on a DB-backed refresh session.
Source code in litestar_auth/authentication/strategy/db.py
list_refresh_sessions(user)
async
¶
Return active refresh sessions belonging to user.
Expired refresh-token rows are deleted before active sessions are returned.
Returns:
| Type | Description |
|---|---|
list[RefreshSession]
|
Active refresh-session metadata ordered by creation time. |
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
revoke_other_refresh_sessions(user, current_session_id)
async
¶
Revoke active refresh sessions for user except current_session_id.
Returns:
| Type | Description |
|---|---|
int
|
Number of active refresh sessions revoked. |
Source code in litestar_auth/authentication/strategy/db.py
revoke_refresh_session(user, session_id)
async
¶
Revoke one active refresh session for user by public session id.
Returns:
| Type | Description |
|---|---|
bool
|
|
Source code in litestar_auth/authentication/strategy/db.py
rotate_refresh_token(refresh_token, user_manager)
async
¶
Rotate a refresh token and return the related user plus replacement.
Returns:
| Type | Description |
|---|---|
tuple[UP, str] | None
|
Tuple of the resolved user and rotated refresh token, or |
Source code in litestar_auth/authentication/strategy/db.py
set_refresh_token_request_context(request)
¶
Capture safe request metadata for the next refresh-token write or rotation.
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
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
write_token(user)
async
¶
Generate a JWT token for the provided user.
Returns:
| Type | Description |
|---|---|
str
|
The encoded JWT token string. |
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 uses a per-user index to delete only the keys associated with the user, avoiding keyspace scans under the global prefix. Tokens that do not have a per-user index entry are left to expire naturally by TTL.
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.