API Reference¶
Complete reference documentation for pico-client-auth's public API.
Module: pico_client_auth¶
Decorators¶
| Decorator | Description |
|---|---|
@allow_anonymous | Skip authentication for an endpoint |
@requires_role(*roles) | Require at least one of the specified roles |
Classes¶
| Class | Description |
|---|---|
SecurityContext | Static accessor for authenticated claims and roles |
TokenClaims | Frozen dataclass with JWT claim fields |
RoleResolver | Protocol for custom role extraction |
AuthClientSettings | Configuration dataclass for auth settings |
Exceptions¶
| Exception | Description |
|---|---|
AuthClientError | Base exception for all pico-client-auth errors |
MissingTokenError | No Bearer token found in request |
TokenExpiredError | JWT token has expired |
TokenInvalidError | JWT is malformed or has invalid signature |
InsufficientPermissionsError | User lacks required role(s) |
AuthConfigurationError | Auth configuration is missing or invalid |
Decorator Reference¶
@allow_anonymous¶
Marks an endpoint as publicly accessible without authentication.
Sets _pico_allow_anonymous = True on the function. The auth middleware checks this attribute before validating the token.
@requires_role¶
Requires the authenticated user to have at least one of the specified roles.
Parameters:
| Parameter | Type | Description |
|---|---|---|
*roles | str | One or more role names (user must have at least one) |
Example:
@requires_role("admin")
async def admin_only(): ...
@requires_role("editor", "admin")
async def editor_or_admin(): ...
Sets _pico_required_roles = frozenset(roles) on the function. The middleware checks this after token validation.
Class Reference¶
SecurityContext¶
Static class for accessing authenticated user state within a request.
| Method | Returns | Raises | Description |
|---|---|---|---|
get() | TokenClaims \| None | -- | Current claims or None |
require() | TokenClaims | MissingTokenError | Current claims (must exist) |
get_roles() | list[str] | -- | Resolved roles (returns copy) |
has_role(role) | bool | -- | Check if user has role |
require_role(*roles) | None | InsufficientPermissionsError | Assert at least one role |
set(claims, roles) | None | -- | Internal: populate context |
clear() | None | -- | Internal: clear context |
TokenClaims¶
Immutable dataclass representing essential JWT claims.
@dataclass(frozen=True)
class TokenClaims:
sub: str # Subject (user ID)
email: str # User email
role: str # Primary role claim
org_id: str # Organisation ID
jti: str # JWT ID
RoleResolver (Protocol)¶
Protocol for custom role extraction from JWT claims.
@runtime_checkable
class RoleResolver(Protocol):
async def resolve(self, claims: TokenClaims, raw_claims: dict) -> list[str]: ...
The default implementation (DefaultRoleResolver) returns [claims.role] if non-empty, else [].
Override by registering a @component that satisfies this protocol.
AuthClientSettings¶
Configuration dataclass loaded from the auth_client config prefix.
@configured(target="self", prefix="auth_client", mapping="tree")
@dataclass
class AuthClientSettings:
enabled: bool = True
issuer: str = ""
audience: str = ""
jwks_ttl_seconds: int = 300
jwks_endpoint: str = ""
accepted_algorithms: tuple[str, ...] = ("RS256",)
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | True | Enable/disable auth middleware |
issuer | str | "" | Expected JWT issuer |
audience | str | "" | Expected JWT audience |
jwks_ttl_seconds | int | 300 | JWKS cache TTL (seconds) |
jwks_endpoint | str | "" | JWKS URL (default: {issuer}/api/v1/auth/jwks) |
accepted_algorithms | tuple[str, ...] | ("RS256",) | Accepted JWT signing algorithms (e.g. RS256, ML-DSA-65, ML-DSA-87) |
Exception Reference¶
AuthClientError¶
Base exception for all pico-client-auth errors.
MissingTokenError¶
Raised when no Bearer token is found in the Authorization header, or when SecurityContext.require() is called without an authenticated context.
TokenExpiredError¶
Raised when the JWT exp claim indicates the token has expired.
TokenInvalidError¶
Raised when the JWT is malformed, has an invalid signature, wrong issuer, or wrong audience.
InsufficientPermissionsError¶
Raised when SecurityContext.require_role() is called and the user lacks all specified roles.
AuthConfigurationError¶
Raised at startup if auth_client.enabled is True but issuer or audience are empty.
Auto-generated API¶
pico_client_auth ¶
pico-client-auth: JWT authentication client for pico-fastapi.
Provides automatic Bearer token validation, a request-scoped SecurityContext, role-based access control decorators, and JWKS key rotation support.
Public API
Models: TokenClaims Context: SecurityContext Decorators: allow_anonymous, requires_role Protocols: RoleResolver Configuration: AuthClientSettings Errors: AuthClientError, MissingTokenError, TokenExpiredError, TokenInvalidError, InsufficientPermissionsError, AuthConfigurationError
AuthClientSettings dataclass ¶
Type-safe settings for the auth client, loaded from configuration sources.
Populated automatically from configuration sources using the auth_client prefix via pico-ioc's @configured decorator.
Attributes:
| Name | Type | Description |
|---|---|---|
enabled | bool | Whether authentication middleware is active. |
issuer | str | Expected JWT issuer ( |
audience | str | Expected JWT audience ( |
jwks_ttl_seconds | int | How long to cache the JWKS key set (seconds). |
jwks_endpoint | str | URL to fetch JWKS from. Defaults to |
Source code in src/pico_client_auth/config.py
AuthClientError ¶
AuthConfigurationError ¶
Bases: AuthClientError
Authentication configuration is missing or invalid.
InsufficientPermissionsError ¶
Bases: AuthClientError
The authenticated user lacks the required role(s).
MissingTokenError ¶
Bases: AuthClientError
No Bearer token found in the Authorization header.
TokenExpiredError ¶
Bases: AuthClientError
The JWT token has expired.
TokenInvalidError ¶
Bases: AuthClientError
The JWT token is malformed or has an invalid signature.
TokenClaims dataclass ¶
Immutable representation of the essential JWT claims.
Attributes:
| Name | Type | Description |
|---|---|---|
sub | str | Subject identifier (user ID). |
email | str | User email address. |
role | str | Primary role claim from the token. |
org_id | str | Organisation identifier. |
jti | str | Unique token identifier (JWT ID). |
Source code in src/pico_client_auth/models.py
RoleResolver ¶
Bases: Protocol
Protocol for resolving user roles from JWT claims.
Implement this protocol to customise how roles are extracted (e.g. from a roles array claim, from an external service, etc.). Register your implementation as a @component and it will automatically replace the default resolver.
Source code in src/pico_client_auth/role_resolver.py
SecurityContext ¶
Singleton-style accessor for the current request's authentication state.
All methods are static; the underlying storage uses ContextVar so each async task / thread has its own isolated copy.
Source code in src/pico_client_auth/security_context.py
get() staticmethod ¶
require() staticmethod ¶
Return the current claims, raising if not authenticated.
Raises:
| Type | Description |
|---|---|
MissingTokenError | If no authentication context is set. |
Source code in src/pico_client_auth/security_context.py
get_roles() staticmethod ¶
has_role(role) staticmethod ¶
require_role(*roles) staticmethod ¶
Assert that the current user has at least one of the given roles.
Raises:
| Type | Description |
|---|---|
InsufficientPermissionsError | If none of the roles match. |
Source code in src/pico_client_auth/security_context.py
get_groups() staticmethod ¶
has_group(group_id) staticmethod ¶
require_group(*group_ids) staticmethod ¶
Assert that the current user belongs to at least one of the given groups.
Raises:
| Type | Description |
|---|---|
InsufficientPermissionsError | If none of the groups match. |
Source code in src/pico_client_auth/security_context.py
set(claims, roles) staticmethod ¶
Populate the security context (called by the middleware).
clear() staticmethod ¶
Clear the security context (called by the middleware in finally).
allow_anonymous(fn) ¶
Mark an endpoint as accessible without authentication.
When applied to a controller method, the auth middleware will skip token validation for that route.
Source code in src/pico_client_auth/decorators.py
requires_group(*group_ids) ¶
Require the authenticated user to belong to at least one of the specified groups.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*group_ids | str | One or more group IDs. The user must belong to at least one. | () |
Returns:
| Type | Description |
|---|---|
Callable[[F], F] | A decorator that attaches group metadata to the endpoint. |
Source code in src/pico_client_auth/decorators.py
requires_role(*roles) ¶
Require the authenticated user to have at least one of the specified roles.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
*roles | str | One or more role names. The user must have at least one. | () |
Returns:
| Type | Description |
|---|---|
Callable[[F], F] | A decorator that attaches role metadata to the endpoint. |