Authentication strategies¶
FastAPIAuth and its strategies. In fastapi_alcazaba.auth; JWTStrategy, OAuth2Strategy,
OIDCStrategy, SAMLStrategy and UnkeyStrategy in fastapi_alcazaba.auth.strategies.jwt,
.oauth2, .oidc, .saml and .unkey, with their extras.
In the guide: Strategies. In an app: the example.
fastapi_alcazaba.auth.FastAPIAuth
¶
FastAPIAuth(*strategies: Strategy, metrics: Metrics | None = None, audit: FastAPIAudit | None = None, actor: Actor | None = None)
The strategies of an app, and the dependencies that authenticate with them.
auth = FastAPIAuth(JWTStrategy(...), SessionStrategy(...))
@app.get("/me")
async def me(user: Annotated[User, Depends(auth.authenticate("jwt", "session"))]): ...
A request is authenticated once: the dependencies of a route that ask for the same strategies get the user the first one found (an API key isn't verified twice).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
strategies
|
Strategy
|
the strategies, by their names; more with |
()
|
metrics
|
Metrics | None
|
where to count the outcomes ( |
None
|
audit
|
FastAPIAudit | None
|
the audit trail that records the failed authentications ( |
None
|
actor
|
Actor | None
|
who the user a strategy found is, in those events: |
None
|
use
¶
use(strategy: S) -> S
Add a strategy, under its name; returns it, with its own type (github.redirect()).
authenticate
¶
authenticate(*names: str, optional: bool = False, scopes: Collection[str] = ()) -> Callable[..., Awaitable[Any]]
A dependency that returns the user of the first of these strategies that finds one
(all of them, in the order they were added, without names). Without one, a 401 with
their challenges (a WebSocket is closed with 1008), or None when optional.
The user's credentials must grant scopes, and those of Security(dependency,
scopes=[...]) where it's used (FastAPI's, which the OpenAPI schema shows); one missing
is a 403 with WWW-Authenticate: Bearer error="insufficient_scope".
user
async
¶
user(connection: HTTPConnection, *names: str) -> Any
The user of the first of these strategies (all of them without names) that finds one; None when none does. For connections that don't go through a dependency.
fastapi_alcazaba.auth.Strategy
¶
Strategy(name: str)
Bases: ABC
One way to tell who makes a request. Subclasses implement authenticate.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
what |
required |
authenticate
abstractmethod
async
¶
authenticate(connection: HTTPConnection) -> Any
The user who makes the request (a Request or a WebSocket); None when it doesn't carry this strategy's credentials. Raises AuthenticationFailed when they're there but wrong.
openapi_scheme
¶
openapi_scheme() -> Callable[..., Any] | None
The FastAPI security scheme that the OpenAPI schema shows for it, for the docs'
Authorize button (HTTPBearer(auto_error=False)...); None for none.
grant
¶
grant(connection: HTTPConnection, scopes: str | Collection[str]) -> None
Record the scopes that the request's credentials grant (a token's scope, a key's),
for the routes that need some: call it in authenticate, with the user found.
fastapi_alcazaba.auth.AuthenticationFailed
¶
Bases: Exception
Raised by a strategy whose credentials are in the request but wrong: an expired token, a forged one, an OAuth2 login the provider refused. The message is logged, never sent.
fastapi_alcazaba.auth.granted_scopes
¶
granted_scopes(connection: HTTPConnection) -> frozenset[str] | None
The scopes the credentials of the request's user grant; None when the strategy that found it grants none (a session, a login).
fastapi_alcazaba.auth.strategies.jwt.JWTStrategy
¶
JWTStrategy(key: Secrets | None = None, *, jwks_url: str | None = None, algorithms: Sequence[str] = ('HS256',), audience: str | None = None, issuer: str | None = None, leeway: float = 0, required: Sequence[str] = ('exp', 'sub'), verify: Callable[[dict[str, Any]], Any] | None = None, blocklist: TokenBlocklist | None = None, cookie: str | None = None, signing_key: Secrets | None = None, jwks_lifespan: float = 300, scope_claims: Sequence[str] = ('scope', 'scp'), name: str = 'jwt')
Bases: Strategy
Authenticates by a JWT in Authorization: Bearer <token> (or a cookie), verified with
key or the provider's JWKS. The signature, exp, nbf and the claims of required are
always checked, aud and iss when given; a token with an aud is refused when no
audience is, as it's meant for some other service. alg: none is never accepted.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
Secrets | None
|
what verifies the tokens: a secret of at least 32 bytes for HS256, HS384 and HS512 (a list rotates them: the first one signs, all of them verify), or a public key (PEM) for RS256, ES256, EdDSA... |
None
|
jwks_url
|
str | None
|
the provider's JWKS instead of |
None
|
algorithms
|
Sequence[str]
|
those accepted; the first one signs what |
('HS256',)
|
audience
|
str | None
|
the |
None
|
issuer
|
str | None
|
the |
None
|
leeway
|
float
|
seconds of tolerance on |
0
|
required
|
Sequence[str]
|
claims a token must have. |
('exp', 'sub')
|
verify
|
Callable[[dict[str, Any]], Any] | None
|
|
None
|
blocklist
|
TokenBlocklist | None
|
refuses the tokens revoked there (by |
None
|
cookie
|
str | None
|
also reads the token from this cookie, for browsers. |
None
|
signing_key
|
Secrets | None
|
what |
None
|
scope_claims
|
Sequence[str]
|
the claims whose scopes the token grants, for the routes that need some
( |
('scope', 'scp')
|
name
|
str
|
what |
'jwt'
|
decode
async
¶
decode(token: str) -> dict[str, Any]
The claims of token, verified; raises AuthenticationFailed when it isn't valid.
issue
¶
issue(subject: str, *, expires_in: int = 900, **claims: Any) -> str
A token for subject, valid for expires_in seconds, with iat, exp, a random
jti, iss and aud when they're set, and claims.
fastapi_alcazaba.auth.strategies.oauth2.OAuth2Strategy
¶
OAuth2Strategy(*, name: str, authorization_url: str, token_url: str, client_id: str, client_secret: str | SecretStr, redirect_uri: str, scopes: Sequence[str] = (), userinfo_url: str | None = None, verify: Callable[[dict[str, Any], dict[str, Any] | None], Any] | None = None, client_auth: Literal['basic', 'post'] = 'basic', params: Mapping[str, str] | None = None, secure: bool = True, timeout: float = 10.0, client: Any = None)
Bases: AuthorizationCodeFlow
Authenticates the requests that come back from the provider's login page (the callback):
checks their state, exchanges their code for tokens, reads the user's profile, and returns
the user that verify makes of them. Other requests carry nothing for it (None): it only
goes on the callback route.
redirect() starts the login: it sends the browser to the provider with a random state
and a PKCE challenge, whose verifier waits in a short-lived cookie (HttpOnly, SameSite=Lax,
__Host- when Secure). A callback without that cookie or with another state is refused:
nobody can log a user in with their own account (login CSRF) nor use a stolen code.
For OpenID Connect providers, OIDCStrategy also verifies the ID token they send.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
what |
required |
authorization_url
|
str
|
the provider's login page. |
required |
token_url
|
str
|
where codes are exchanged for tokens. |
required |
client_id
|
str
|
the app's id at the provider. |
required |
client_secret
|
str | SecretStr
|
the app's secret at the provider. |
required |
redirect_uri
|
str
|
the callback's absolute URL, as registered at the provider. |
required |
scopes
|
Sequence[str]
|
what to ask the provider for. |
()
|
userinfo_url
|
str | None
|
where to read the user's profile with the access token; None for none. |
None
|
verify
|
Callable[[dict[str, Any], dict[str, Any] | None], Any] | None
|
|
None
|
client_auth
|
Literal['basic', 'post']
|
how the app authenticates to the token endpoint: |
'basic'
|
params
|
Mapping[str, str] | None
|
more parameters for the login page ( |
None
|
secure
|
bool
|
the cookie is Secure (browsers accept it from http://localhost too). |
True
|
timeout
|
float
|
seconds for each call to the provider. |
10.0
|
client
|
Any
|
the httpx2 client to call the provider with; one of its own by default. |
None
|
fastapi_alcazaba.auth.strategies.oidc.OIDCStrategy
¶
OIDCStrategy(*, name: str, issuer: str, client_id: str, client_secret: str | SecretStr, redirect_uri: str, scopes: Sequence[str] = ('openid', 'email', 'profile'), verify: Callable[[dict[str, Any], dict[str, Any] | None], Any] | None = None, userinfo: bool = False, max_age: int | None = None, algorithms: Sequence[str] = ('RS256', 'ES256', 'PS256', 'EdDSA'), leeway: float = 60, authorization_url: str | None = None, token_url: str | None = None, userinfo_url: str | None = None, jwks_url: str | None = None, jwks_lifespan: float = 3600, client_auth: Literal['basic', 'post'] = 'basic', params: Mapping[str, str] | None = None, secure: bool = True, timeout: float = 10.0, client: Any = None)
Bases: AuthorizationCodeFlow
Authenticates the callback of an OpenID Connect login: exchanges its code for tokens,
verifies the ID token, and returns the user that verify makes of its claims.
The ID token is refused unless it's signed with one of algorithms by a key of the
provider's JWKS (never none, never with the client secret), comes from issuer, is meant
for this app (aud has client_id, and azp is it when there are several audiences or an
azp), hasn't expired (exp) nor was issued in the future (iat), carries the nonce
the login sent, the at_hash of the access token when it has one, and an auth_time within
max_age when it's set. A provider that sends no ID token is refused.
Its endpoints and keys come from the issuer's discovery document
(/.well-known/openid-configuration), read by await discover() in the lifespan; whose
issuer must be issuer exactly. Endpoints given here aren't read from it, and with all of
them (authorization_url, token_url, jwks_url) there's nothing to discover.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
what |
required |
issuer
|
str
|
the provider's issuer identifier, as its ID tokens have it in |
required |
client_id
|
str
|
the app's id at the provider: the ID tokens' audience. |
required |
client_secret
|
str | SecretStr
|
the app's secret at the provider. |
required |
redirect_uri
|
str
|
the callback's absolute URL, as registered at the provider. |
required |
scopes
|
Sequence[str]
|
what to ask for; |
('openid', 'email', 'profile')
|
verify
|
Callable[[dict[str, Any], dict[str, Any] | None], Any] | None
|
|
None
|
userinfo
|
bool
|
also read the userinfo endpoint, for claims the ID token doesn't carry. |
False
|
max_age
|
int | None
|
seconds since the user last entered their credentials at the provider, at
most: sent as |
None
|
algorithms
|
Sequence[str]
|
the signature algorithms accepted. |
('RS256', 'ES256', 'PS256', 'EdDSA')
|
leeway
|
float
|
seconds of tolerance on |
60
|
authorization_url
|
str | None
|
the login page, instead of discovery's. |
None
|
token_url
|
str | None
|
where codes are exchanged for tokens, instead of discovery's. |
None
|
userinfo_url
|
str | None
|
the userinfo endpoint, instead of discovery's. |
None
|
jwks_url
|
str | None
|
the provider's keys, instead of discovery's. |
None
|
jwks_lifespan
|
float
|
seconds the keys are kept before they're fetched again. |
3600
|
client_auth
|
Literal['basic', 'post']
|
how the app authenticates to the token endpoint: |
'basic'
|
params
|
Mapping[str, str] | None
|
more parameters for the login page ( |
None
|
secure
|
bool
|
the cookie is Secure (browsers accept it from http://localhost too). |
True
|
timeout
|
float
|
seconds for each call to the provider. |
10.0
|
client
|
Any
|
the httpx2 client to call the provider with; one of its own by default. |
None
|
discover
async
¶
discover() -> None
Read the provider's discovery document: its endpoints and where its keys are, for those not given. Raises RuntimeError when it can't be read, or doesn't fit.
verify_id_token
async
¶
verify_id_token(id_token: str, *, nonce: str, access_token: str | None = None) -> dict[str, Any]
The claims of id_token, verified as the class says; AuthenticationFailed when it
isn't valid. nonce is the login's, and access_token the one it came with.
fastapi_alcazaba.auth.strategies.oauth2.AuthorizationCodeFlow
¶
AuthorizationCodeFlow(*, name: str, client_id: str, client_secret: str | SecretStr, redirect_uri: str, scopes: Sequence[str], client_auth: Literal['basic', 'post'], params: Mapping[str, str] | None, secure: bool, timeout: float, client: Any)
Bases: Strategy
The authorization code flow with PKCE, which OAuth2Strategy and OIDCStrategy share:
redirect() sends the browser to the provider, and the callback's request is authenticated
by its code. Subclasses set the endpoints and implement _finish.
redirect() starts the login: it sends the browser to the provider with a random state
and a PKCE challenge, whose verifier waits in a short-lived cookie (HttpOnly, SameSite=Lax,
__Host- when Secure). A callback without that cookie or with another state is refused:
nobody can log a user in with their own account (login CSRF) nor use a stolen code.
redirect
¶
redirect(**params: str) -> RedirectResponse
The response that sends the browser to the provider's login page, with params added
to the URL; it sets the cookie that the callback checks.
fastapi_alcazaba.auth.SessionStrategy
¶
SessionStrategy(load_user: Callable[[Any], Any], *, key: str = 'user_id', name: str = 'session')
Bases: Strategy
Authenticates by the user id that login kept in the session, with ServerSessionMiddleware
(or Starlette's SessionMiddleware).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
load_user
|
Callable[[Any], Any]
|
|
required |
key
|
str
|
where in the session the user id is kept. |
'user_id'
|
name
|
str
|
what |
'session'
|
login
¶
login(connection: HTTPConnection, user_id: Any) -> None
Keep user_id (a JSON value) in the session: the next requests are that user's. With
ServerSessionMiddleware the session gets a new id, so that one someone planted in the
browser before (session fixation) doesn't log them in too.
logout
¶
logout(connection: HTTPConnection) -> None
Empty the session; with ServerSessionMiddleware it's also deleted from the backend.
fastapi_alcazaba.auth.HTTPBearerStrategy
¶
HTTPBearerStrategy(verify: Callable[[str], Any], *, realm: str | None = None, scopes_of: Callable[[Any], str | Collection[str]] | None = None, name: str = 'bearer')
Bases: Strategy
Authenticates by the token of Authorization: Bearer <token>, which verify turns into
the user. A token that isn't RFC 6750's syntax, or longer than 4 KiB, fails without reaching
verify.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
verify
|
Callable[[str], Any]
|
|
required |
realm
|
str | None
|
the realm of the 401's challenge, |
None
|
scopes_of
|
Callable[[Any], str | Collection[str]] | None
|
|
None
|
name
|
str
|
what |
'bearer'
|
fastapi_alcazaba.auth.strategies.saml.SAMLStrategy
¶
SAMLStrategy(*, entity_id: str, acs_url: str, idp_entity_id: str, idp_sso_url: str, idp_certificate: str | Sequence[str], verify: Callable[[SAMLProfile], Any] | None = None, name_id_format: str | None = None, clock_skew: float = 60, cache: Cache | None = None, name: str = 'saml')
Bases: Strategy
Authenticates the requests the IdP posts to the Assertion Consumer Service (the ACS):
checks the signature of their response with the IdP's certificate, and that it answers the
login this browser started; the user is what verify makes of the profile. Other requests
carry nothing for it (None): it only goes on the ACS route.
redirect() starts the login (SP-initiated: logins the IdP starts by itself aren't accepted).
The id of its request waits in a short-lived cookie (__Host-, HttpOnly, Secure, and
SameSite=None: the IdP posts to the ACS from its own site), and the answer must carry it.
Checked on what the signature covers: the issuer, the audience (entity_id), the recipient
(acs_url), the request it answers, when it's valid (with clock_skew), and that it's a
bearer assertion. Each assertion works once: its id is kept in the cache's backend until it
expires, so a copy is refused by every process. Not supported: encrypted assertions, signed
requests, single logout.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
entity_id
|
str
|
this app's entity id at the IdP (its "SP entity id", or "audience"). |
required |
acs_url
|
str
|
the ACS's absolute URL, where the IdP posts its answers. |
required |
idp_entity_id
|
str
|
the IdP's entity id, the issuer of its answers. |
required |
idp_sso_url
|
str
|
the IdP's single sign-on URL (HTTP-Redirect binding). |
required |
idp_certificate
|
str | Sequence[str]
|
the IdP's signing certificate (PEM); a list while it rotates them. signxml refuses expired ones. |
required |
verify
|
Callable[[SAMLProfile], Any] | None
|
|
None
|
name_id_format
|
str | None
|
the NameID format to ask for ( |
None
|
clock_skew
|
float
|
seconds of tolerance on the validity times, for clocks out of step. |
60
|
cache
|
Cache | None
|
the Cache whose backend remembers the assertions used; FastAPICache's by default. When it fails, logins are refused. |
None
|
name
|
str
|
what |
'saml'
|
redirect
¶
redirect(relay_state: str | None = None) -> RedirectResponse
The response that sends the browser to the IdP with an AuthnRequest, and sets the
cookie that the ACS checks. relay_state comes back in the profile (a page to return
to; check it before redirecting there).
metadata
¶
metadata() -> str
This app's metadata, for the IdP: its entity id, ACS and NameID format.
fastapi_alcazaba.auth.strategies.saml.SAMLProfile
dataclass
¶
SAMLProfile(name_id: str, name_id_format: str | None, issuer: str, session_index: str | None, attributes: Mapping[str, list[str]] = dict(), relay_state: str | None = None)
Who the IdP says logged in, from its signed assertion.
fastapi_alcazaba.auth.strategies.unkey.UnkeyStrategy
¶
UnkeyStrategy(unkey: UnkeyClient, verify: Callable[[UnkeyKey], Any] | None = None, *, permissions: str | None = None, cost: int = 1, ratelimits: Sequence[str] = (), keyspaces: Sequence[str] = (), tags: Sequence[str] = (), header: str | None = None, credits_status: int = HTTP_429_TOO_MANY_REQUESTS, name: str = 'unkey', metrics: Metrics | None = None)
Bases: Strategy
Authenticates by an API key that Unkey verifies: Authorization: Bearer <key> by default,
or the header header. Each request is one verification, which spends the key's credits and
counts in its rate limits: nothing is cached, so a key deleted or disabled is refused at once
(Unkey takes up to 30 seconds to spread a deletion).
What Unkey answers:
VALID: the user isverify(key)(anUnkeyKey), the key itself withoutverify.NOT_FOUND,DISABLED,EXPIRED: authentication fails (a 401, or the next strategy).INSUFFICIENT_PERMISSIONS,FORBIDDEN: a 403; the key is valid, it may not do this.RATE_LIMITED: a 429 withRetry-After;USAGE_EXCEEDED(no credits left): a 429, or a 402 withcredits_status=402.- Unkey down, slow (
timeout) or limiting the workspace: a 503. A root key without the verify permission: UnkeyError, a 500.
A route that needs other permissions or costs more credits has a strategy of its own, with
another name and the same client: UnkeyStrategy(verifier, name="unkey-admin",
permissions="admin.*").
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
unkey
|
UnkeyClient
|
the client, with a root key that may verify keys. |
required |
verify
|
Callable[[UnkeyKey], Any] | None
|
|
None
|
permissions
|
str | None
|
what the key must have, in Unkey's query syntax:
|
None
|
cost
|
int
|
credits each verification spends (0 for none); a key without a credit limit spends nothing. |
1
|
ratelimits
|
Sequence[str]
|
names of the key's (or its identity's) rate limits to apply besides those it applies by itself. |
()
|
keyspaces
|
Sequence[str]
|
the keyspaces (APIs) the key must belong to; any by default. |
()
|
tags
|
Sequence[str]
|
tags for Unkey's analytics, |
()
|
header
|
str | None
|
the header the key comes in ( |
None
|
credits_status
|
int
|
what a key out of credits gets: 429, or 402 (Payment Required). |
HTTP_429_TOO_MANY_REQUESTS
|
name
|
str
|
what |
'unkey'
|
metrics
|
Metrics | None
|
where to count the verifications ( |
None
|
fastapi_alcazaba.auth.strategies.unkey.UnkeyClient
¶
UnkeyClient(root_key: str | SecretStr, *, url: str = UNKEY_URL, timeout: float = 2.0, client: AsyncClient | None = None)
Calls Unkey's API with a root key. Each call has a deadline, and Unkey a circuit breaker: when it's down, calls fail at once instead of each waiting for it.
Give each use its own root key, with only the permissions it needs: one that may only verify
keys for UnkeyStrategy, another that may create and delete them for UnkeyKeys.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
root_key
|
str | SecretStr
|
the root key (a |
required |
url
|
str
|
Unkey's API. |
UNKEY_URL
|
timeout
|
float
|
seconds for each call, the answer included. |
2.0
|
client
|
AsyncClient | None
|
the httpx2 client to call it with (a proxy, a transport of your own); one of its
own by default, with a |
None
|
call
async
¶
call(operation: str, body: Mapping[str, Any]) -> tuple[dict[str, Any], str | None]
POST /v2/<operation> with body: Unkey's data, and its ID of the request. Raises
UnkeyUnavailable when it doesn't answer (or answers 5xx or 429), and UnkeyError when it
refuses the call.
aclose
async
¶
aclose() -> None
Closes the client it made (not one it was given): in the lifespan, at shutdown.
fastapi_alcazaba.auth.strategies.unkey.UnkeyKeys
¶
UnkeyKeys(unkey: UnkeyClient, api_id: str, *, prefix: str | None = None)
Issues and revokes the keys of an Unkey API: for the page where your users make theirs.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
unkey
|
UnkeyClient
|
the client, with a root key that may create and delete keys of |
required |
api_id
|
str
|
the Unkey API the keys belong to. |
required |
prefix
|
str | None
|
what the keys start with ( |
None
|
create
async
¶
create(*, external_id: str | None = None, name: str | None = None, expires: datetime | None = None, credits_left: int | None = None, refill: CreditRefill | None = None, ratelimits: Sequence[KeyRatelimit] = (), permissions: Sequence[str] = (), roles: Sequence[str] = (), meta: Mapping[str, Any] | None = None) -> CreatedKey
A new key, whose key to show its owner once. external_id ties it to its owner in
your app (verifications give it back); credits_left are the uses it has (None for no
limit), which refill gives back; expires is when it stops working.
delete
async
¶
delete(key_id: str, *, permanent: bool = False) -> None
Delete a key: its verifications fail within 30 seconds. permanent erases it whole
(its hash and metadata too); otherwise Unkey can still bring it back.
fastapi_alcazaba.auth.strategies.unkey.UnkeyKey
dataclass
¶
UnkeyKey(key_id: str, name: str | None = None, external_id: str | None = None, meta: Mapping[str, Any] = dict(), permissions: tuple[str, ...] = (), roles: tuple[str, ...] = (), credits: int | None = None, expires: datetime | None = None, ratelimits: tuple[RatelimitState, ...] = (), request_id: str | None = None)
A key Unkey verified, what UnkeyStrategy gives verify (or the endpoint).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key_id
|
str
|
Unkey's ID of the key, to update or delete it. |
required |
name
|
str | None
|
the key's name. |
None
|
external_id
|
str | None
|
the ID of its identity in your app (the user, the tenant), when it has one. |
None
|
meta
|
Mapping[str, Any]
|
what was stored with the key. |
dict()
|
permissions
|
tuple[str, ...]
|
its permissions, those of its roles included (when some were checked). |
()
|
roles
|
tuple[str, ...]
|
its roles (when permissions were checked). |
()
|
credits
|
int | None
|
the credits left; None when it has no limit. |
None
|
expires
|
datetime | None
|
when it expires; None when it doesn't. |
None
|
ratelimits
|
tuple[RatelimitState, ...]
|
its rate limits, as this verification left them. |
()
|
request_id
|
str | None
|
Unkey's ID of the verification, for its support. |
None
|
fastapi_alcazaba.auth.strategies.unkey.RatelimitState
dataclass
¶
RatelimitState(name: str, limit: int, remaining: int, reset: float, exceeded: bool)
A rate limit of a key, as its verification left it.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
the limit's name. |
required |
limit
|
int
|
requests per window. |
required |
remaining
|
int
|
requests left in the window. |
required |
reset
|
float
|
seconds until the window starts again. |
required |
exceeded
|
bool
|
whether this request went past it. |
required |
fastapi_alcazaba.auth.strategies.unkey.CreatedKey
dataclass
¶
CreatedKey(key: SecretStr, key_id: str)
A key UnkeyKeys.create made.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
key
|
SecretStr
|
the key, to show its owner once: Unkey only keeps its hash. |
required |
key_id
|
str
|
Unkey's ID of the key, to keep, to delete it later. |
required |
fastapi_alcazaba.auth.strategies.unkey.KeyRatelimit
dataclass
¶
KeyRatelimit(name: str, limit: int, duration: timedelta, auto_apply: bool = True)
A rate limit to give a new key: limit requests per duration.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
name
|
str
|
what verifications name it by (3 to 128 characters). |
required |
limit
|
int
|
requests per window. |
required |
duration
|
timedelta
|
the window, a second or more. |
required |
auto_apply
|
bool
|
applied to every verification, without naming it. |
True
|
fastapi_alcazaba.auth.strategies.unkey.CreditRefill
dataclass
¶
CreditRefill(amount: int, interval: Literal['daily', 'monthly'] = 'monthly', day: int | None = None)
Credits given back to a key every day or month.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
amount
|
int
|
the credits it gets back. |
required |
interval
|
Literal['daily', 'monthly']
|
daily or monthly. |
'monthly'
|
day
|
int | None
|
for monthly refills, the day of the month (1 to 31). |
None
|
fastapi_alcazaba.auth.strategies.unkey.UnkeyError
¶
UnkeyError(status: int | None, detail: str, request_id: str | None = None)
Bases: RuntimeError
Unkey refused a call: a root key without the permission, a request it can't take. A mistake to fix, not a refusal of the key: a 500.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
status
|
int | None
|
the HTTP status Unkey answered. |
required |
detail
|
str
|
Unkey's explanation. |
required |
request_id
|
str | None
|
Unkey's ID of the request, for its support. |
None
|
fastapi_alcazaba.auth.strategies.unkey.UnkeyUnavailable
¶
UnkeyUnavailable(status: int | None, detail: str, request_id: str | None = None)
Bases: UnkeyError
Unkey didn't answer, answered too slowly, with a 5xx, or limited the workspace (a 429): the requests are refused with a 503.