OAuth router helpers¶
The litestar_auth.oauth package uses lazy imports (PEP 562) so optional dependencies such as
httpx-oauth are not loaded until OAuth helpers are used. If your IDE does not resolve symbols on
litestar_auth.oauth, import from litestar_auth.oauth.router directly—the module that
implements the helpers re-exported from the package.
These helpers cover the supported manual OAuth client contract used by create_provider_oauth_controller(),
create_oauth_controller(), and OAuthClientAdapter.
For direct provider-login assembly, ProviderOAuthControllerConfig(...) carries the same settings accepted by
create_provider_oauth_controller(...) as keyword arguments.
- Typed contract:
litestar_auth.oauth._client.OAuthClientProtocolwith the narrowerOAuthDirectIdentityClientProtocol,OAuthProfileClientProtocol, and optionalOAuthEmailVerificationAsyncClientProtocolcapability protocols. Wrap sync-only verification clients withmake_async_email_verification_client(). - Provisioning: pass
oauth_client,oauth_client_factory, oroauth_client_classplusoauth_client_kwargs. - Flow-cookie secret: every manual controller factory requires
oauth_flow_cookie_secretfor the encrypted, authenticated OAuth state + PKCE verifier cookie. The secret is HKDF-derived into Fernet key material for the short-livedv2flow-cookie envelope. - Authorization: the client must provide
get_authorization_url(...) -> strand accept PKCE S256 challenge keyword arguments. - Token exchange: the client must provide
get_access_token(...)with anaccess_tokenpayload and accept the PKCEcode_verifierkeyword argument. - Identity: provide
get_id_email(...)orget_profile(...)with account id and email fields. - Optional verification: provide async
get_email_verified(...)or anemail_verifiedfield on the profile payload. - Invalid import paths, missing methods, or malformed payloads fail closed with
ConfigurationError.
See OAuth2 login and account linking for the full behavioral contract.
Token encryption policy¶
OAuth token persistence is configured with OAuthConfig.oauth_token_encryption_keyring for
plugin-managed routes or with an explicit OAuthTokenEncryption(...) policy for direct
SQLAlchemyUserDatabase(...) usage. Encrypted stored values use the
fernet:v1:<key_id>:<ciphertext> envelope. The one-key oauth_token_encryption_key shortcut and
OAuthTokenEncryption(key=...) path write with the default key id; use a
FernetKeyringConfig(active_key_id=..., keys=...) or OAuthTokenEncryption(active_key_id=..., keys=...)
when you need rotation.
OAuthTokenEncryption.requires_reencrypt(value) and OAuthTokenEncryption.reencrypt(value) operate
on one stored token value at a time. Migration jobs should apply them to both access_token and
refresh_token columns, commit rewritten values, scan again, and remove retired key ids only after
no rows require rotation. Legacy unversioned Fernet values need explicit old-key migration input
because the stored value does not identify its decrypting key.
These public helpers fail closed unless the policy has a configured key/keyring or explicitly sets
unsafe_testing=True; keyless plaintext mode is only a test-owned override.
litestar_auth.oauth_encryption
¶
Explicit OAuth token encryption helpers for SQLAlchemy-backed persistence.
OAuth token storage is bound to a concrete session via
bind_oauth_token_encryption(...) or by passing oauth_token_encryption=...
to SQLAlchemyUserDatabase. Mapped OAuthAccount instances keep plaintext
tokens in memory while mapper events encrypt them before writes and decrypt them
after loads/refreshes.
OAuthTokenEncryption(key=None, unsafe_testing=False, active_key_id=_DEFAULT_OAUTH_FERNET_KEY_ID, keys=None)
dataclass
¶
Explicit OAuth token encryption policy for one session-bound persistence path.
__post_init__()
¶
Initialize the cached Fernet keyring for this policy's key.
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
If both one-key and keyring inputs are configured. |
Source code in litestar_auth/oauth_encryption.py
decrypt(value)
¶
Return the value decrypted with this policy, or plaintext in explicit unsafe tests.
Source code in litestar_auth/oauth_encryption.py
encrypt(value)
¶
Return the value encrypted with this policy, or plaintext in explicit unsafe tests.
Source code in litestar_auth/oauth_encryption.py
reencrypt(value)
¶
Return a stored OAuth token rewritten with the active key.
Source code in litestar_auth/oauth_encryption.py
require_configured(*, context='OAuth token persistence')
¶
Fail closed when encryption is required but no key is configured.
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
When |
Source code in litestar_auth/oauth_encryption.py
requires_reencrypt(value)
¶
Return whether a stored OAuth token should be rewritten with the active key.
Source code in litestar_auth/oauth_encryption.py
bind_oauth_token_encryption(session, oauth_token_encryption)
¶
Bind an explicit OAuth token encryption policy to a SQLAlchemy session path.
Raises:
| Type | Description |
|---|---|
TypeError
|
When |
Source code in litestar_auth/oauth_encryption.py
get_bound_oauth_token_encryption(session)
¶
Return the OAuth token encryption policy bound to the given session path.
Source code in litestar_auth/oauth_encryption.py
register_oauth_model_encryption_events(model_base)
¶
Register mapper events that keep OAuth token attributes plaintext in memory.
Source code in litestar_auth/oauth_encryption.py
require_oauth_token_encryption(oauth_token_encryption, *, context='OAuth token persistence')
¶
Return the explicit policy or fail when persistence would rely on ambient state.
Raises:
| Type | Description |
|---|---|
ConfigurationError
|
When no explicit policy was supplied, or when a policy without a
configured key is used while |
Source code in litestar_auth/oauth_encryption.py
Public OAuth helpers are implemented in litestar_auth.oauth.router (the litestar_auth.oauth package re-exports them lazily).
The old litestar_auth.contrib.oauth package is no longer a compatibility import path.
litestar_auth.oauth.router
¶
Helpers for constructing provider-specific OAuth controllers.
ProviderOAuthControllerConfig(provider_name, backend, user_manager, redirect_base_url, oauth_flow_cookie_secret, oauth_client=None, oauth_client_factory=None, oauth_client_class=None, oauth_client_kwargs=None, auth_path='/auth', path=None, cookie_secure=True, oauth_scopes=None, associate_by_email=False, trust_provider_email_verified=False, oauth_redirect_dns_strict=True)
dataclass
¶
Configuration for :func:create_provider_oauth_controller.
ProviderOAuthControllerOptions
¶
Bases: TypedDict
Keyword options accepted by :func:create_provider_oauth_controller.
create_provider_oauth_controller(*, config=None, **options)
¶
Build a provider-specific OAuth controller from a client or lazy factory.
The authorize endpoint uses only server-configured oauth_scopes. Runtime
scope-query overrides are rejected. redirect_base_url must use a
non-loopback https:// origin; the manual controller API does not expose
a debug or testing override for insecure callback origins. The generated
flow encrypts transient state + PKCE verifier material with
oauth_flow_cookie_secret and enforces RFC 7636 PKCE S256, so manual
clients must accept code_challenge / code_challenge_method on
authorization and code_verifier on token exchange.
Returns:
| Type | Description |
|---|---|
type[Controller]
|
Generated controller class mounted under the provider-specific path. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If |
Source code in litestar_auth/oauth/router.py
load_httpx_oauth_client(oauth_client_class, /, **client_kwargs)
¶
Import and instantiate an httpx-oauth client lazily.
Returns:
| Type | Description |
|---|---|
OAuthClientProtocol
|
Instantiated OAuth client. |
Raises:
| Type | Description |
|---|---|
ImportError
|
If the optional |
ModuleNotFoundError
|
If a non- |
ConfigurationError
|
If the client path is invalid or the class cannot be imported. |