Skip to content

API Reference

The auth sources, validators, token helpers, and core exceptions import directly from fastapi_multiauth:

from fastapi_multiauth import (
    APIKeyHeaderAuth,
    APIKeyQueryAuth,
    AuthSource,
    HTTPBasicAuth,
    HTTPBearerAuth,
    APIKeyCookieAuth,
    ForbiddenError,
    JWTValidator,
    MultiAuth,
    OAuth2AuthorizationCodeBearerAuth,
    OAuth2PasswordBearerAuth,
    OpenIdConnectAuth,
    RouteAuth,
    SchemeRequirement,
    UnauthorizedError,
    auth_surface,
    hash_token,
    verify_token_hash,
)

The OAuth 2.0 / OIDC login-flow helpers are a separate concern: they obtain credentials via the browser redirect flow rather than validating credentials on an incoming request, and they require the oauth extra. They live in the fastapi_multiauth.oauth namespace:

from fastapi_multiauth.oauth import (
    OAuthDiscoveryError,
    OAuthError,
    OAuthExchangeError,
    OAuthUserinfoError,
    OIDCEndpoints,
    oauth_build_authorization_redirect,
    oauth_decode_state,
    oauth_encode_state,
    oauth_exchange_code,
    oauth_fetch_userinfo,
    oauth_generate_pkce_pair,
    oauth_generate_state_token,
    oauth_resolve_provider_urls,
)

Sources

fastapi_multiauth.AuthSource

Bases: ABC

Abstract base class for authentication sources.

Subclasses implement :meth:extract and :meth:authenticate; both Security(source) and MultiAuth route through that pair via :meth:dispatch.

__call__(**kwargs) async

FastAPI dependency dispatch.

__init__(scheme=None)

Set up the FastAPI dependency signature.

Parameters:

Name Type Description Default
scheme Any

Optional fastapi.security scheme; only its OpenAPI metadata is used, extraction always goes through :meth:extract.

None

authenticate(credential) abstractmethod async

Validate a credential and return the authenticated identity.

authenticate_scoped(credential, scopes, *, request=None) async

Validate a credential, enforcing the scopes declared on the route.

Parameters:

Name Type Description Default
credential str

The raw credential returned by :meth:extract.

required
scopes list[str]

The scopes the route declared, empty outside a route.

required
request Request | None

The request being authenticated, None when there is none. Ignored here; override to use it.

None

dispatch(request, scopes) async

Extract the credential, then authenticate it with the route scopes.

Raises:

Type Description
UnauthorizedError

When no credential is present. This source's WWW-Authenticate challenge is attached to any 401 raised.

RuntimeError

When an :meth:optional copy meets a route that declares scopes, which an anonymous caller could never satisfy.

extract(request) abstractmethod async

Extract the raw credential from the request without validating.

Must return None — never an empty string — when the credential is absent, empty, or does not belong to this source.

optional()

Return a copy that yields None instead of 401 when no credential is sent.

www_authenticate()

Challenge value for the WWW-Authenticate header on 401 responses.

Returns None when the source has no HTTP auth scheme (cookies, API keys).

fastapi_multiauth.HTTPBearerAuth

Bases: _BearerSource

Bearer token authentication source (wraps HTTPBearer for OpenAPI).

The validator is called as await validator(credential, **kwargs).

Parameters:

Name Type Description Default
validator Callable[..., Any]

Sync or async callable returning the identity; raises :class:~fastapi_multiauth.exceptions.UnauthorizedError on failure.

required
prefix str | None

Optional token prefix (e.g. "user_"); only tokens with this prefix are matched, and the prefix is kept in the validated value.

None
scheme_name str | None

OpenAPI security scheme name (default HTTPBearer); give each source a distinct name when several appear in the same app.

None
description str | None

Optional prose for the OpenAPI security scheme object.

None
bearer_format str | None

Optional hint at the token format (e.g. "JWT"), for documentation only.

None
token_generator Callable[[int], str]

Callable building the token body from the nbytes :meth:generate_token is given, owning its alphabet and entropy; prefix is still prepended. Defaults to secrets.token_urlsafe. Use a CSPRNG (:mod:secrets), never :mod:random.

token_urlsafe
**kwargs Any

Extra keyword arguments forwarded to the validator on every call.

{}

__call__(**kwargs) async

FastAPI dependency dispatch.

authenticate(credential, *, request=None) async

Validate a credential and return the identity (no route scopes).

authenticate_scoped(credential, scopes, *, request=None) async

Validate the credential, re-checking the prefix and forwarding scopes.

dispatch(request, scopes) async

Extract the credential, then authenticate it with the route scopes.

Raises:

Type Description
UnauthorizedError

When no credential is present. This source's WWW-Authenticate challenge is attached to any 401 raised.

RuntimeError

When an :meth:optional copy meets a route that declares scopes, which an anonymous caller could never satisfy.

extract(request) async

Return the bearer token, or None when absent, empty, or mismatched.

The Bearer scheme is matched case-insensitively; the prefix, when configured, is kept in the returned value.

generate_token(nbytes=32)

Generate a token with token_generator, prefixed when configured.

Parameters:

Name Type Description Default
nbytes int

Number of random bytes, handed to the token_generator, which decides what to make of it.

32

Returns:

Type Description
str

A ready-to-use token string (e.g. "user_Xk3...").

Raises:

Type Description
ValueError

If the generator returns an empty token, or one that leaves the final token with leading or trailing whitespace.

optional()

Return a copy that yields None instead of 401 when no credential is sent.

require(**kwargs)

Return a copy of this source with additional (or overriding) validator kwargs.

Reserved names (scopes, session_id, request) are rejected here too.

www_authenticate()

Bearer challenge per RFC 6750 §3.

fastapi_multiauth.APIKeyCookieAuth

Bases: ValidatedAuthSource

Cookie-based authentication source (wraps APIKeyCookie for OpenAPI).

When secret_key is set, the cookie is signed (HMAC-SHA256 with an embedded timestamp, salted by the cookie name) for stateless, tamper-proof sessions; otherwise the raw cookie value is passed through.

Parameters:

Name Type Description Default
name str

Cookie name.

required
validator Callable[..., Any]

Sync or async callable receiving the cookie value (plain, after signature verification when signed) and returning the identity.

required
secret_key str | Sequence[str] | None

One key or a sequence to rotate (first signs, all verify); each at least 32 bytes. When None, the cookie is not signed.

None
session_id bool

Mint a random id per :meth:set_cookie and inject it into the validator as session_id. Requires secret_key and a validator declaring that parameter; changing it invalidates existing cookies.

False
ttl int

Cookie lifetime in seconds (default 24 h); also enforced server-side when the cookie is signed.

86400
secure bool

Set the Secure flag (default True); disable only in local dev.

True
samesite SameSite

SameSite cookie attribute (default "lax").

'lax'
domain str | None

Optional Domain cookie attribute.

None
path str

Path cookie attribute (default "/").

'/'
scheme_name str | None

OpenAPI security scheme name (default APIKeyCookie_{name}).

None
description str | None

Optional prose for the OpenAPI security scheme object.

None
**kwargs Any

Extra keyword arguments forwarded to the validator on every call.

{}

name property

Cookie name. Read-only: the signing salt is derived from it.

ttl property

Cookie lifetime in seconds: use it to derive your session's expiry.

__call__(**kwargs) async

FastAPI dependency dispatch.

authenticate(credential, *, request=None) async

Validate a credential and return the identity (no route scopes).

authenticate_scoped(credential, scopes, *, request=None) async

Verify the cookie, forwarding route-declared scopes to the validator.

Clear the session cookie (logout) from this client only.

Returns request's session id when it verifies (revoke it server-side for a hard logout), None otherwise.

dispatch(request, scopes) async

Extract the credential, then authenticate it with the route scopes.

Raises:

Type Description
UnauthorizedError

When no credential is present. This source's WWW-Authenticate challenge is attached to any 401 raised.

RuntimeError

When an :meth:optional copy meets a route that declares scopes, which an anonymous caller could never satisfy.

extract(request) async

Return the raw cookie value, or None when absent or empty.

optional()

Return a copy that yields None instead of 401 when no credential is sent.

require(**kwargs)

Return a copy of this source with additional (or overriding) validator kwargs.

Reserved names (scopes, session_id, request) are rejected here too.

session_id_of(request)

Return request's session id without running the validator.

None when session_id is off, or the cookie is absent, expired or forged.

Attach the cookie to response, signing it when secret_key is set.

Returns the minted session id: always a str when session_id is on, always None when it is off.

www_authenticate()

Challenge value for the WWW-Authenticate header on 401 responses.

Returns None when the source has no HTTP auth scheme (cookies, API keys).

fastapi_multiauth.APIKeyHeaderAuth

Bases: ValidatedAuthSource

API key header authentication source (wraps APIKeyHeader for OpenAPI).

The validator is called as await validator(api_key, **kwargs).

Parameters:

Name Type Description Default
name str

HTTP header name that carries the API key (e.g. "X-API-Key").

required
validator Callable[..., Any]

Sync or async callable returning the identity; raises :class:~fastapi_multiauth.exceptions.UnauthorizedError on failure.

required
scheme_name str | None

OpenAPI security scheme name (default APIKeyHeader_{name}).

None
description str | None

Optional prose for the OpenAPI security scheme object.

None
**kwargs Any

Extra keyword arguments forwarded to the validator on every call.

{}

__call__(**kwargs) async

FastAPI dependency dispatch.

authenticate(credential, *, request=None) async

Validate a credential and return the identity (no route scopes).

authenticate_scoped(credential, scopes, *, request=None) async

Validate a credential, forwarding route scopes and request to the validator.

dispatch(request, scopes) async

Extract the credential, then authenticate it with the route scopes.

Raises:

Type Description
UnauthorizedError

When no credential is present. This source's WWW-Authenticate challenge is attached to any 401 raised.

RuntimeError

When an :meth:optional copy meets a route that declares scopes, which an anonymous caller could never satisfy.

extract(request) async

Return the API key from the configured header, or None when absent or empty.

optional()

Return a copy that yields None instead of 401 when no credential is sent.

require(**kwargs)

Return a copy of this source with additional (or overriding) validator kwargs.

Reserved names (scopes, session_id, request) are rejected here too.

www_authenticate()

Challenge value for the WWW-Authenticate header on 401 responses.

Returns None when the source has no HTTP auth scheme (cookies, API keys).

fastapi_multiauth.APIKeyQueryAuth

Bases: ValidatedAuthSource

API key query-string authentication source (wraps APIKeyQuery for OpenAPI).

The validator is called as await validator(api_key, **kwargs).

.. warning:: Credentials in the query string leak into access logs, browser history, and Referer headers. Prefer a header or cookie when you can; use this only for clients that cannot set headers.

Parameters:

Name Type Description Default
name str

Query parameter name that carries the API key (e.g. "api_key").

required
validator Callable[..., Any]

Sync or async callable returning the identity; raises :class:~fastapi_multiauth.exceptions.UnauthorizedError on failure.

required
scheme_name str | None

OpenAPI security scheme name (default APIKeyQuery_{name}).

None
description str | None

Optional prose for the OpenAPI security scheme object.

None
**kwargs Any

Extra keyword arguments forwarded to the validator on every call.

{}

__call__(**kwargs) async

FastAPI dependency dispatch.

authenticate(credential, *, request=None) async

Validate a credential and return the identity (no route scopes).

authenticate_scoped(credential, scopes, *, request=None) async

Validate a credential, forwarding route scopes and request to the validator.

dispatch(request, scopes) async

Extract the credential, then authenticate it with the route scopes.

Raises:

Type Description
UnauthorizedError

When no credential is present. This source's WWW-Authenticate challenge is attached to any 401 raised.

RuntimeError

When an :meth:optional copy meets a route that declares scopes, which an anonymous caller could never satisfy.

extract(request) async

Return the API key from the configured query parameter, or None when absent or empty.

optional()

Return a copy that yields None instead of 401 when no credential is sent.

require(**kwargs)

Return a copy of this source with additional (or overriding) validator kwargs.

Reserved names (scopes, session_id, request) are rejected here too.

www_authenticate()

Challenge value for the WWW-Authenticate header on 401 responses.

Returns None when the source has no HTTP auth scheme (cookies, API keys).

fastapi_multiauth.HTTPBasicAuth

Bases: ValidatedAuthSource

HTTP Basic authentication source (wraps HTTPBasic for OpenAPI, RFC 7617).

The validator is called as await validator(username, password, **kwargs); compare the password in constant time (secrets.compare_digest).

Parameters:

Name Type Description Default
validator Callable[..., Any]

Sync or async callable receiving (username, password) and returning the identity; raises :class:~fastapi_multiauth.exceptions.UnauthorizedError on failure.

required
realm str | None

Optional protection-space name for the WWW-Authenticate.

None
scheme_name str | None

OpenAPI security scheme name (default HTTPBasic).

None
description str | None

Optional prose for the OpenAPI security scheme object.

None
**kwargs Any

Extra keyword arguments forwarded to the validator on every call.

{}

__call__(**kwargs) async

FastAPI dependency dispatch.

authenticate(credential, *, request=None) async

Validate a credential and return the identity (no route scopes).

authenticate_scoped(credential, scopes, *, request=None) async

Decode the blob, forwarding route-declared scopes to the validator.

dispatch(request, scopes) async

Extract the credential, then authenticate it with the route scopes.

Raises:

Type Description
UnauthorizedError

When no credential is present. This source's WWW-Authenticate challenge is attached to any 401 raised.

RuntimeError

When an :meth:optional copy meets a route that declares scopes, which an anonymous caller could never satisfy.

extract(request) async

Return the base64 credentials blob, or None when absent or empty.

The Basic scheme is matched case-insensitively; decoding and the split happen in :meth:authenticate, so a malformed blob is a 401.

optional()

Return a copy that yields None instead of 401 when no credential is sent.

require(**kwargs)

Return a copy of this source with additional (or overriding) validator kwargs.

Reserved names (scopes, session_id, request) are rejected here too.

www_authenticate()

Basic challenge, with the realm when configured (RFC 7617 §2).

fastapi_multiauth.OAuth2AuthorizationCodeBearerAuth

Bases: _BearerSource

Bearer tokens issued by an authorization-code flow.

Parameters:

Name Type Description Default
validator Callable[..., Any]

Sync or async callable returning the identity.

required
authorization_url str

URL the Authorize dialog sends the user to.

required
token_url str

URL that exchanges the code for a token.

required
refresh_url str | None

Optional refresh endpoint.

None
scopes dict[str, str] | None

Catalogue of scope names mapped to their descriptions.

None
scheme_name str | None

OpenAPI security scheme name.

None
description str | None

Optional prose for the OpenAPI security scheme object.

None
**kwargs Any

Extra keyword arguments forwarded to the validator.

{}

__call__(**kwargs) async

FastAPI dependency dispatch.

authenticate(credential, *, request=None) async

Validate a credential and return the identity (no route scopes).

authenticate_scoped(credential, scopes, *, request=None) async

Validate the credential, re-checking the prefix and forwarding scopes.

dispatch(request, scopes) async

Extract the credential, then authenticate it with the route scopes.

Raises:

Type Description
UnauthorizedError

When no credential is present. This source's WWW-Authenticate challenge is attached to any 401 raised.

RuntimeError

When an :meth:optional copy meets a route that declares scopes, which an anonymous caller could never satisfy.

extract(request) async

Return the bearer token, or None when absent, empty, or mismatched.

The Bearer scheme is matched case-insensitively; the prefix, when configured, is kept in the returned value.

optional()

Return a copy that yields None instead of 401 when no credential is sent.

require(**kwargs)

Return a copy of this source with additional (or overriding) validator kwargs.

Reserved names (scopes, session_id, request) are rejected here too.

www_authenticate()

Bearer challenge per RFC 6750 §3.

fastapi_multiauth.OAuth2PasswordBearerAuth

Bases: _BearerSource

Bearer tokens issued by a password-grant token endpoint.

Parameters:

Name Type Description Default
validator Callable[..., Any]

Sync or async callable returning the identity.

required
token_url str

URL of the token endpoint, as advertised to OpenAPI.

required
scopes dict[str, str] | None

Catalogue of scope names mapped to their descriptions.

None
scheme_name str | None

OpenAPI security scheme name.

None
description str | None

Optional prose for the OpenAPI security scheme object.

None
**kwargs Any

Extra keyword arguments forwarded to the validator.

{}

__call__(**kwargs) async

FastAPI dependency dispatch.

authenticate(credential, *, request=None) async

Validate a credential and return the identity (no route scopes).

authenticate_scoped(credential, scopes, *, request=None) async

Validate the credential, re-checking the prefix and forwarding scopes.

dispatch(request, scopes) async

Extract the credential, then authenticate it with the route scopes.

Raises:

Type Description
UnauthorizedError

When no credential is present. This source's WWW-Authenticate challenge is attached to any 401 raised.

RuntimeError

When an :meth:optional copy meets a route that declares scopes, which an anonymous caller could never satisfy.

extract(request) async

Return the bearer token, or None when absent, empty, or mismatched.

The Bearer scheme is matched case-insensitively; the prefix, when configured, is kept in the returned value.

optional()

Return a copy that yields None instead of 401 when no credential is sent.

require(**kwargs)

Return a copy of this source with additional (or overriding) validator kwargs.

Reserved names (scopes, session_id, request) are rejected here too.

www_authenticate()

Bearer challenge per RFC 6750 §3.

fastapi_multiauth.OpenIdConnectAuth

Bases: _BearerSource

Bearer tokens issued by an OpenID Connect provider.

Parameters:

Name Type Description Default
validator Callable[..., Any]

Sync or async callable returning the identity.

required
openid_connect_url str

The provider's .well-known discovery URL.

required
scheme_name str | None

OpenAPI security scheme name.

None
description str | None

Optional prose for the OpenAPI security scheme object.

None
**kwargs Any

Extra keyword arguments forwarded to the validator.

{}

__call__(**kwargs) async

FastAPI dependency dispatch.

authenticate(credential, *, request=None) async

Validate a credential and return the identity (no route scopes).

authenticate_scoped(credential, scopes, *, request=None) async

Validate the credential, re-checking the prefix and forwarding scopes.

dispatch(request, scopes) async

Extract the credential, then authenticate it with the route scopes.

Raises:

Type Description
UnauthorizedError

When no credential is present. This source's WWW-Authenticate challenge is attached to any 401 raised.

RuntimeError

When an :meth:optional copy meets a route that declares scopes, which an anonymous caller could never satisfy.

extract(request) async

Return the bearer token, or None when absent, empty, or mismatched.

The Bearer scheme is matched case-insensitively; the prefix, when configured, is kept in the returned value.

optional()

Return a copy that yields None instead of 401 when no credential is sent.

require(**kwargs)

Return a copy of this source with additional (or overriding) validator kwargs.

Reserved names (scopes, session_id, request) are rejected here too.

www_authenticate()

Bearer challenge per RFC 6750 §3.

fastapi_multiauth.MultiAuth

Combine multiple authentication sources into a single callable.

Sources are tried in declaration order through the same extract()/ authenticate() pair used by direct Security(source) access.

Parameters:

Name Type Description Default
*sources AuthSource

Auth source instances to try in order.

()

Raises:

Type Description
TypeError

If a source is not an :class:AuthSource instance.

dispatch(request, scopes) async

Authenticate with the first source whose credential is present.

optional()

Return a copy that yields None when no source has a credential.

require(**kwargs)

Return a new :class:MultiAuth with kwargs forwarded to each source.

www_authenticate()

Combined challenge of all sources (RFC 9110 §11.6.1), or None.

Validators

fastapi_multiauth.JWTValidator

Validate JWTs — plug directly into :class:~fastapi_multiauth.HTTPBearerAuth.

Requires the jwt extra. Configure exactly one of secret (symmetric HS*) or jwks_url (asymmetric, against the provider's JWKS).

Parameters:

Name Type Description Default
secret str | None

Symmetric key for HS* validation (at least 32 bytes).

None
jwks_url str | None

HTTPS URL of the provider's JWKS document.

None
algorithms Sequence[str] | None

Accepted signature algorithms. Defaults to ["HS256"] in secret mode and ["RS256", "ES256"] in JWKS mode. Symmetric algorithms are rejected in JWKS mode (key-confusion risk).

None
audience str | Sequence[str] | None

Expected aud claim value(s). Unset → aud not checked.

None
issuer str | None

Expected iss claim value. Unset → iss not checked.

None
leeway float

Clock-skew tolerance in seconds for time-based claims.

0.0
required_claims Sequence[str]

Claims that must be present (default ("exp",)).

('exp',)
scopes_claim str

Claim holding granted scopes — a space-separated string (scope) or a list (scp, roles). A valid token missing a route-declared scope raises a 403.

'scope'
claims_to_identity Callable[[dict[str, Any]], Any] | None

Optional sync or async hook mapping verified claims to a domain object. Defaults to returning the claims.

None
jwks_cache_ttl float

JWKS cache lifetime in seconds (default 1 h).

3600.0
jwks_refresh_cooldown float

Minimum interval in seconds between JWKS fetch attempts (default 30 s).

30.0
timeout float

Timeout in seconds for the JWKS request.

DEFAULT_TIMEOUT

__call__(token, scopes=None) async

Verify token and return the identity.

Raises:

Type Description
UnauthorizedError

Invalid/expired signature or claims (401).

ForbiddenError

Valid token missing route-required scopes (403).

HTTPException

503 when the JWKS cannot be fetched and no keys are cached — the token cannot be checked either way.

Introspection

fastapi_multiauth.auth_surface(app)

Report the authentication requirements of every route in app.

Parameters:

Name Type Description Default
app FastAPI

The application to inspect. A mounted sub-application is opaque, so call this on the sub-application as well.

required

Returns:

Name Type Description
One list[RouteAuth]

class:RouteAuth per routed endpoint, in registration order.

list[RouteAuth]

WebSocket routes are included with no methods; routes carrying no

list[RouteAuth]

dependency tree, such as /docs, are skipped.

fastapi_multiauth.RouteAuth dataclass

What guards one route.

Parameters:

Name Type Description Default
path str

Full routed path, including any router prefix.

required
methods tuple[str, ...]

HTTP methods, sorted; empty for a WebSocket route.

required
alternatives tuple[tuple[SchemeRequirement, ...], ...]

Ways to satisfy the route, OR-ed; the schemes within one are AND-ed. A :class:MultiAuth contributes one entry per source, separate Security() dependencies share an entry, and dependencies that resolve alike count once. Empty when nothing guards the route.

required
scopes tuple[str, ...]

Every scope named on the route, first-seen order. An inventory for filtering, not a requirement: what one credential must carry is the scope list of the entry in alternatives it satisfies.

required
unguarded bool

Whether a credential-less request reaches the endpoint. True when nothing guards the route, and when every AND-ed position offers a scheme that does not refuse it. An optional of None counts as one, so an unreadable guard is reported.

required
include_in_schema bool

Whether the route appears in app.openapi(). False for include_in_schema=False and for WebSocket routes.

required

fastapi_multiauth.SchemeRequirement dataclass

One authentication scheme a route accepts, with the scopes it checks.

Parameters:

Name Type Description Default
scheme_name str | None

OpenAPI security scheme name, None for a source carrying no fastapi.security scheme.

required
source str

Name of the class enforcing it, e.g. "HTTPBearerAuth".

required
scopes tuple[str, ...]

Scopes this scheme must check, in declaration order. A dependency declared in several positions carries the union.

required
optional bool | None

Whether an absent credential is accepted, None when the scheme does not say. Read from auto_error, and always False inside a required :class:MultiAuth.

required

Token helpers

fastapi_multiauth.hash_token(token)

Return the SHA-256 hex digest of an opaque token.

Parameters:

Name Type Description Default
token str

The opaque token, including any prefix.

required

Returns:

Type Description
str

A 64-character lowercase hex digest.

fastapi_multiauth.verify_token_hash(token, stored_hash)

Compare a presented token against a stored hash in constant time.

Parameters:

Name Type Description Default
token str

The opaque token presented by the client.

required
stored_hash str

The hex digest previously stored via :func:hash_token.

required

Returns:

Type Description
bool

True if the token matches the stored hash.

Exceptions

fastapi_multiauth.UnauthorizedError

Bases: HTTPException

HTTP 401 — authentication credentials were missing or invalid.

Raise from a validator (or any HTTPException) to reject a credential.

__init__(detail='Unauthorized', headers=None)

Initialize the exception.

Parameters:

Name Type Description Default
detail str

Human-readable message returned in the response body.

'Unauthorized'
headers dict[str, str] | None

Extra response headers (e.g. WWW-Authenticate).

None

fastapi_multiauth.ForbiddenError

Bases: HTTPException

HTTP 403 — the identity is authenticated but lacks permission.

Keep 401 (:class:UnauthorizedError) for absent or invalid credentials.

__init__(detail='Forbidden', headers=None)

Initialize the exception.

Parameters:

Name Type Description Default
detail str

Human-readable message returned in the response body.

'Forbidden'
headers dict[str, str] | None

Extra response headers.

None

OAuth helpers

The OAuth login-flow helpers live in the fastapi_multiauth.oauth namespace and require the oauth extra (pip install fastapi-multiauth[oauth]). See OAuth 2.0 / OIDC login for the walkthrough.

fastapi_multiauth.oauth.OAuthError

Bases: Exception

Base class for OAuth flow errors.

Not an HTTPException: the route decides the HTTP outcome of a failed flow.

fastapi_multiauth.oauth.OAuthDiscoveryError

Bases: OAuthError

Raised when the OIDC discovery document cannot be fetched or is invalid.

fastapi_multiauth.oauth.OAuthExchangeError

Bases: OAuthError

Raised when the OAuth authorization code exchange fails.

fastapi_multiauth.oauth.OAuthUserinfoError

Bases: OAuthError

Raised when the userinfo endpoint cannot be reached or returns garbage.

fastapi_multiauth.oauth.OIDCEndpoints

Bases: NamedTuple

Validated endpoint URLs from an OIDC discovery document.

All URLs are HTTPS-checked (loopback hosts excepted). Optional fields are None when the provider does not advertise them.

fastapi_multiauth.oauth.oauth_resolve_provider_urls(discovery_url, timeout=DEFAULT_TIMEOUT) async

Fetch the OIDC discovery document and return its validated endpoints.

Cached for one hour. The discovery URL must come from configuration, never from request input (SSRF / cache-poisoning).

Parameters:

Name Type Description Default
discovery_url str

Provider's openid-configuration URL.

required
timeout float

Discovery request timeout in seconds.

DEFAULT_TIMEOUT

Returns:

Name Type Description
Validated OIDCEndpoints

class:OIDCEndpoints; optional fields are None when absent.

Raises:

Type Description
ValueError

If discovery_url is not HTTPS.

OAuthDiscoveryError

If the document is unreachable, malformed, or advertises non-HTTPS endpoints or a mismatched issuer.

fastapi_multiauth.oauth.oauth_exchange_code(*, token_url, code, client_id, client_secret, redirect_uri, required_scopes=None, code_verifier=None, token_endpoint_auth_method='client_secret_post', timeout=DEFAULT_TIMEOUT, client=None) async

Exchange an authorization code for tokens and return the token response.

Delegates the exchange (including PKCE) to httpx-oauth (the oauth extra).

Parameters:

Name Type Description Default
token_url str

Provider's token endpoint.

required
code str

Authorization code from the provider's callback.

required
client_id str

OAuth application client ID.

required
client_secret str

OAuth application client secret.

required
redirect_uri str

Redirect URI used in the authorization request.

required
required_scopes str | None

Space-separated scopes that must be present in the token response (RFC 6749 §3.3).

None
code_verifier str | None

PKCE code verifier matching the challenge sent earlier (from :func:~fastapi_multiauth.oauth.oauth_generate_pkce_pair).

None
token_endpoint_auth_method TokenEndpointAuthMethod

How credentials are sent — in the POST body (client_secret_post, default) or as a Basic header.

'client_secret_post'
timeout float

Timeout in seconds for the token request. Ignored when client is provided.

DEFAULT_TIMEOUT
client AsyncClient | None

Optional httpx.AsyncClient to reuse (connection pooling across the login flow). Borrowed, not closed; its own configuration (timeouts included) governs the request.

None

Returns:

Type Description
dict[str, Any]

The full token response as a dict (access_token plus whatever

dict[str, Any]

else the provider returned).

Raises:

Type Description
ValueError

If token_url is not HTTPS.

OAuthExchangeError

If the exchange is rejected or fails, grants a non-bearer token, or omits a required scope.

fastapi_multiauth.oauth.oauth_fetch_userinfo(*, userinfo_url, access_token, timeout=DEFAULT_TIMEOUT, client=None) async

Fetch the userinfo payload with a bearer access token.

Parameters:

Name Type Description Default
userinfo_url str

Provider's userinfo endpoint.

required
access_token str

Access token from :func:oauth_exchange_code.

required
timeout float

Timeout in seconds for the userinfo request. Ignored when client is provided.

DEFAULT_TIMEOUT
client AsyncClient | None

Optional httpx.AsyncClient to reuse (connection pooling across the login flow). Borrowed, not closed; its own configuration (timeouts included) governs the request.

None

Returns:

Type Description
dict[str, Any]

The JSON payload returned by the userinfo endpoint as a plain dict.

Raises:

Type Description
ValueError

If userinfo_url is not HTTPS.

OAuthUserinfoError

If the endpoint fails or does not return JSON.

fastapi_multiauth.oauth.oauth_generate_state_token()

Generate a cryptographically random CSRF token for the OAuth state parameter.

fastapi_multiauth.oauth.oauth_generate_pkce_pair()

Generate a PKCE (code_verifier, code_challenge) pair (RFC 7636, S256).

Store the verifier server-side and pass it back to :func:~fastapi_multiauth.oauth.oauth_exchange_code on the callback.

Returns:

Type Description
str

A (code_verifier, code_challenge) tuple; the challenge is the

str

base64url SHA-256 of the verifier.

fastapi_multiauth.oauth.oauth_build_authorization_redirect(authorization_url, *, client_id, scopes, redirect_uri, destination, state_token, code_challenge=None)

Return an OAuth 2.0 authorization RedirectResponse (303 See Other).

Parameters:

Name Type Description Default
authorization_url str

Provider's authorization endpoint.

required
client_id str

OAuth application client ID.

required
scopes str

Space-separated list of requested scopes.

required
redirect_uri str

URI the provider should redirect back to.

required
destination str

Post-login URL (embedded in state).

required
state_token str

CSRF token from :func:oauth_generate_state_token; verify it with :func:oauth_decode_state on the callback.

required
code_challenge str | None

PKCE challenge from :func:oauth_generate_pkce_pair; when set, code_challenge_method=S256 is sent along.

None

Returns:

Name Type Description
A RedirectResponse

class:~fastapi.responses.RedirectResponse to the provider's

RedirectResponse

authorization page, retaining any query string already present.

fastapi_multiauth.oauth.oauth_encode_state(url, state_token)

Encode a destination URL and CSRF token into an OAuth state parameter.

Parameters:

Name Type Description Default
url str

Post-login destination URL.

required
state_token str

CSRF token from :func:oauth_generate_state_token.

required

fastapi_multiauth.oauth.oauth_decode_state(state, *, expected_state_token, fallback, allowed_hosts=())

Decode and CSRF-verify an OAuth state parameter (constant-time).

The stored token is single-use: delete it from the session after this call, matched or not, so a captured callback cannot be replayed.

Parameters:

Name Type Description Default
state str | None

Raw state query parameter from the callback.

required
expected_state_token str

Token stored before the authorization redirect; a mismatch — or an empty token (e.g. a session miss) — returns fallback.

required
fallback str

URL returned when state is absent, malformed, or fails verification.

required
allowed_hosts Sequence[str] | None

Open-redirect guard — the decoded destination must be a relative path or an absolute http(s) URL whose host is listed. The default (()) allows relative paths only; None disables the check.

()

Returns:

Type Description
str

The destination URL embedded in state, or fallback.