API Reference#
This page contains the full API reference for axioms-fastapi, automatically generated from the source code docstrings.
Core Configuration#
The SDK requires the following environment variables to be configured:
Parameter |
Required |
Description |
|---|---|---|
|
Yes |
Expected audience claim in the JWT token. |
|
No |
Axioms domain name. Used as the base to construct |
|
No |
Full issuer URL for validating the |
|
No |
Full URL to JWKS endpoint (e.g.,
|
Important
Either AXIOMS_JWKS_URL, AXIOMS_ISS_URL, or AXIOMS_DOMAIN must be configured for token validation.
Configuration Hierarchy:
The SDK uses the following construction order:
AXIOMS_DOMAIN→ constructs →AXIOMS_ISS_URL(if not explicitly set)AXIOMS_ISS_URL→ constructs →AXIOMS_JWKS_URL(if not explicitly set)
Example: Setting only AXIOMS_DOMAIN=auth.example.com/oauth results in:
AXIOMS_ISS_URL:https://auth.example.com/oauthAXIOMS_JWKS_URL:https://auth.example.com/oauth/.well-known/jwks.json
Security & Algorithm Validation#
The SDK implements multiple security best practices to prevent common JWT attacks:
Algorithm Validation
Only secure asymmetric algorithms are accepted for JWT signature verification. The SDK validates that:
The
algheader in the JWT specifies an allowed algorithmEach key is used with exactly one algorithm
The algorithm validation occurs before cryptographic operations
Supported Algorithms:
RSA: RS256, RS384, RS512
ECDSA: ES256, ES384, ES512
RSA-PSS: PS256, PS384, PS512
Rejected Algorithms:
none- No signature (critical security vulnerability)HS256,HS384,HS512- Symmetric algorithms (prevents key confusion attacks)Any algorithm not in the allowed list above
This prevents algorithm confusion attacks where an attacker might try to:
Use the
nonealgorithm to bypass signature verificationSubstitute an asymmetric algorithm with a symmetric one
Use weak or deprecated algorithms
Additional Security Features:
Issuer validation (
issclaim) to prevent token substitutionAutomatic public key retrieval and validation from JWKS endpoints
Token expiration validation
Audience claim validation
Key ID (
kid) validation
Claim Name Mapping#
Configure custom claim names to support different authorization servers (AWS Cognito, Auth0, Okta, Microsoft Entra). These mapping options provide additional customization for claim names used to extract scopes, roles, and permissions from the JWT token. These mappings can also support RFC 9068 JWT Profile for OAuth 2.0 Access Tokens.
Parameter |
Required |
Description |
|---|---|---|
|
No |
List of scope claim names to check in priority order. Default: Example: |
|
No |
List of role claim names to check in priority order. Default: Example: |
|
No |
List of permission claim names to check in priority order. Default: Example: |
Important
Namespaced Claims: You can specify namespaced claim names directly in the claim configuration lists.
The SDK will check claims in the order you specify them, using the first non-None value found.
Example: AXIOMS_ROLES_CLAIMS = ['roles', 'https://myapp.com/claims/roles', 'cognito:groups']
Setting Environment Variables#
You can set these environment variables using a .env file with python-dotenv:
Create a
.envfile in your project rootAdd your configuration:
# Required AXIOMS_AUDIENCE=your-api-audience-or-resource-identifier # Option 1: Use AXIOMS_DOMAIN AXIOMS_DOMAIN=your-domain.axioms.io # Option 2: Use AXIOMS_JWKS_URL (takes precedence) # AXIOMS_JWKS_URL=https://my-auth.domain.com/oauth2/.well-known/jwks.json
Load the environment variables in your FastAPI app:
from fastapi import FastAPI from dotenv import load_dotenv import os load_dotenv() app = FastAPI()
Alternatively, you can set environment variables directly in your application or deployment environment.
import os
os.environ['AXIOMS_AUDIENCE'] = 'your-api-audience'
os.environ['AXIOMS_JWKS_URL'] = 'https://my-auth.domain.com/oauth2/.well-known/jwks.json'
Dependencies#
The dependencies module provides FastAPI dependency functions for authentication and authorization.
FastAPI dependencies for authentication and authorization.
This module provides FastAPI dependency functions for protecting routes with JWT-based authentication and authorization. Supports scope-based, role-based, permission-based, and object-level ownership access control with configurable claim names for different authorization servers.
Example:
from fastapi import FastAPI, Depends
from axioms_fastapi import require_auth, require_scopes, check_object_ownership, init_axioms
app = FastAPI()
init_axioms(app, AXIOMS_AUDIENCE="api.example.com", AXIOMS_DOMAIN="auth.example.com")
@app.get("/protected")
async def protected_route(payload=Depends(require_auth)):
return {"user": payload.sub}
@app.get("/admin")
async def admin_route(payload=Depends(require_auth), _=Depends(require_scopes(["admin"]))):
return {"message": "Admin access"}
@app.patch("/articles/{article_id}")
async def update_article(
article_id: int,
article=Depends(check_object_ownership(get_article))
):
return {"message": "Updated"}
- require_auth(request, config=Depends(dependency=<function get_config>, use_cache=True, scope=None), safe_methods=None)[source]#
FastAPI dependency to require valid JWT authentication.
Validates the JWT access token in the Authorization header and returns the validated payload for use in the route handler.
- Parameters:
request (Request) – FastAPI Request object containing HTTP headers.
config (AxiomsConfig) – Axioms configuration (injected via dependency).
safe_methods (List[str]) – List of HTTP methods that skip authentication. Defaults to [‘OPTIONS’] for CORS preflight requests.
- Returns:
- Validated JWT token payload with claims accessible as attributes.
Returns empty Box for safe methods.
- Return type:
Box
- Raises:
AxiomsHTTPException – If token is missing, invalid, or expired (not raised for safe methods).
Example:
@app.get("/api/protected") async def protected_route(payload=Depends(require_auth)): user_id = payload.sub return {"user_id": user_id}
Example with custom safe methods:
from functools import partial # Allow GET and OPTIONS without auth require_auth_safe = partial(require_auth, safe_methods=["GET", "OPTIONS"]) @app.get("/api/public-read") async def public_route(payload=Depends(require_auth_safe)): # Returns empty Box for GET requests return {"data": "public"}
- require_scopes(required_scopes)[source]#
Create a FastAPI dependency to enforce scope-based authorization.
Checks if the authenticated user’s token contains any of the required scopes. Uses OR logic: the token must have at least ONE of the specified scopes.
- Parameters:
required_scopes (List[str]) – List of required scope strings.
- Returns:
FastAPI dependency function that enforces scope check.
- Return type:
Callable
- Raises:
AxiomsHTTPException – If token doesn’t contain required scopes.
Example (OR logic - requires EITHER scope):
@app.get("/api/resource") async def resource_route( payload=Depends(require_auth), _=Depends(require_scopes(["read:resource", "write:resource"])) ): return {"data": "protected"}
Example (AND logic - requires BOTH scopes via chaining):
@app.get("/api/strict") async def strict_route( payload=Depends(require_auth), _=Depends(require_scopes(["read:resource"])), __=Depends(require_scopes(["write:resource"])) ): return {"data": "requires both scopes"}
- require_roles(required_roles)[source]#
Create a FastAPI dependency to enforce role-based authorization.
Checks if the authenticated user’s token contains any of the required roles. Uses OR logic: the token must have at least ONE of the specified roles.
- Parameters:
- Returns:
FastAPI dependency function that enforces role check.
- Return type:
Callable
- Raises:
AxiomsHTTPException – If token doesn’t contain required roles.
Example (OR logic - requires EITHER role):
@app.get("/admin/users") async def admin_route( payload=Depends(require_auth), _=Depends(require_roles(["admin", "superuser"])) ): return {"users": []}
Example (AND logic - requires BOTH roles via chaining):
@app.get("/admin/critical") async def critical_route( payload=Depends(require_auth), _=Depends(require_roles(["admin"])), __=Depends(require_roles(["superuser"])) ): return {"message": "requires both roles"}
- require_permissions(required_permissions)[source]#
Create a FastAPI dependency to enforce permission-based authorization.
Checks if the authenticated user’s token contains any of the required permissions. Uses OR logic: the token must have at least ONE of the specified permissions.
- Parameters:
required_permissions (List[str]) – List of required permission strings.
- Returns:
FastAPI dependency function that enforces permission check.
- Return type:
Callable
- Raises:
AxiomsHTTPException – If token doesn’t contain required permissions.
Example (OR logic - requires EITHER permission):
@app.get("/api/resource") async def resource_route( payload=Depends(require_auth), _=Depends(require_permissions(["resource:read", "resource:write"])) ): return {"data": "success"}
Example (AND logic - requires BOTH permissions via chaining):
@app.get("/api/critical") async def critical_route( payload=Depends(require_auth), _=Depends(require_permissions(["resource:read"])), __=Depends(require_permissions(["resource:admin"])) ): return {"message": "requires both permissions"}
- check_object_ownership(get_object, owner_field='user', claim_field='sub')[source]#
Create a FastAPI dependency to enforce object-level ownership permissions.
Validates that the authenticated user owns the requested object by comparing a field in the object with a claim in the JWT token. This enables per-object access control where users can only access resources they own.
- Parameters:
- Returns:
FastAPI dependency function that enforces object ownership check.
- Return type:
Callable
- Raises:
400 Bad Request: If object is missing the specified owner_field. - 403 Forbidden: If JWT is missing the claim_field or user doesn’t own the object.
Example (basic usage with defaults):
async def get_article(article_id: int): article = db.query(Article).filter(Article.id == article_id).first() if not article: raise HTTPException(status_code=404, detail="Not found") return article @app.patch("/articles/{article_id}") async def update_article( article_id: int, title: str, article = Depends(check_object_ownership(get_article)) ): article.title = title return article
Example (custom owner field):
@app.delete("/comments/{comment_id}") async def delete_comment( comment_id: int, comment = Depends(check_object_ownership(get_comment, owner_field="created_by")) ): db.delete(comment) return {"message": "Deleted"}
Example (match by email instead of sub):
@app.patch("/users/{user_id}") async def update_user( user_id: int, name: str, user = Depends(check_object_ownership( get_user, owner_field="owner_email", claim_field="email" )) ): user.name = name return user
Example (with SQLAlchemy):
class Article(Base): __tablename__ = "articles" id = Column(Integer, primary_key=True) title = Column(String) user = Column(String) def get_article(article_id: int, db: Session = Depends(get_db)): article = db.query(Article).filter(Article.id == article_id).first() if not article: raise HTTPException(status_code=404, detail="Not found") return article @app.patch("/articles/{article_id}") async def update_article( article_id: int, title: str, article: Article = Depends(check_object_ownership(get_article)), db: Session = Depends(get_db) ): article.title = title db.commit() return article
Token Validation#
The token module handles JWT token validation and verification.
Error Handling#
The error module defines custom exceptions for authentication and authorization errors.
Error handling for Axioms FastAPI authentication and authorization.
This module defines custom exceptions for authentication and authorization errors in FastAPI applications.
- exception AxiomsError(error, status_code=401)[source]#
Bases:
ExceptionBase exception for Axioms authentication and authorization errors.
- Parameters:
Example:
raise AxiomsError( {"error": "unauthorized_access", "error_description": "Invalid token"}, 401 )
- exception AxiomsHTTPException(error, status_code=401, realm=None)[source]#
Bases:
HTTPExceptionFastAPI HTTP exception for Axioms errors.
This exception is compatible with FastAPI’s exception handling system. It includes WWW-Authenticate header for 401 and 403 responses.
- Parameters:
Example:
raise AxiomsHTTPException( {"error": "invalid_token", "error_description": "Token expired"}, 401, "https://auth.example.com" )
Note
401 responses: Authentication failure (missing/invalid token)
403 responses: Authorization failure (insufficient permissions)
- register_axioms_exception_handler(app)[source]#
Register the Axioms exception handler with the FastAPI application.
This convenience function registers a default exception handler for
AxiomsHTTPExceptionexceptions. The handler returns appropriate HTTP status codes and includes theWWW-Authenticateheader for 401 and 403 responses.- Parameters:
app (FastAPI) – FastAPI application instance.
- Return type:
None
Example:
from fastapi import FastAPI from axioms_fastapi.error import register_axioms_exception_handler app = FastAPI() register_axioms_exception_handler(app)
Note
The exception handler is already configured in the
AxiomsHTTPExceptionclass with proper headers and status codes. This function simply registers a handler that returns the exception details in a JSON response.
Configuration#
The config module provides configuration management for the SDK.
Configuration management for Axioms FastAPI.
This module provides configuration classes for managing Axioms settings in FastAPI applications.
- class AxiomsConfig(_case_sensitive=None, _nested_model_default_partial_update=None, _env_prefix=None, _env_file=PosixPath('.'), _env_file_encoding=None, _env_ignore_empty=None, _env_nested_delimiter=None, _env_nested_max_split=None, _env_parse_none_str=None, _env_parse_enums=None, _cli_prog_name=None, _cli_parse_args=None, _cli_settings_source=None, _cli_parse_none_str=None, _cli_hide_none_type=None, _cli_avoid_json=None, _cli_enforce_required=None, _cli_use_class_docs_for_groups=None, _cli_exit_on_error=None, _cli_prefix=None, _cli_flag_prefix_char=None, _cli_implicit_flags=None, _cli_ignore_unknown_args=None, _cli_kebab_case=None, _cli_shortcuts=None, _secrets_dir=None, *, AXIOMS_AUDIENCE, AXIOMS_DOMAIN=None, AXIOMS_ISS_URL=None, AXIOMS_JWKS_URL=None, AXIOMS_SCOPE_CLAIMS=None, AXIOMS_ROLES_CLAIMS=None, AXIOMS_PERMISSIONS_CLAIMS=None, **values)[source]#
Bases:
BaseSettingsConfiguration for Axioms FastAPI authentication.
All settings can be set via environment variables with the AXIOMS_ prefix.
Example:
config = AxiomsConfig( AXIOMS_AUDIENCE="api.example.com", AXIOMS_DOMAIN="auth.example.com" )
- Parameters:
_case_sensitive (bool | None)
_nested_model_default_partial_update (bool | None)
_env_prefix (str | None)
_env_file (DotenvType | None)
_env_file_encoding (str | None)
_env_ignore_empty (bool | None)
_env_nested_delimiter (str | None)
_env_nested_max_split (int | None)
_env_parse_none_str (str | None)
_env_parse_enums (bool | None)
_cli_prog_name (str | None)
_cli_settings_source (CliSettingsSource[Any] | None)
_cli_parse_none_str (str | None)
_cli_hide_none_type (bool | None)
_cli_avoid_json (bool | None)
_cli_enforce_required (bool | None)
_cli_use_class_docs_for_groups (bool | None)
_cli_exit_on_error (bool | None)
_cli_prefix (str | None)
_cli_flag_prefix_char (str | None)
_cli_implicit_flags (bool | None)
_cli_ignore_unknown_args (bool | None)
_cli_kebab_case (bool | Literal['all', 'no_enums'] | None)
_secrets_dir (PathType | None)
AXIOMS_AUDIENCE (str)
AXIOMS_DOMAIN (str | None)
AXIOMS_ISS_URL (str | None)
AXIOMS_JWKS_URL (str | None)
values (Any)
- model_config: ClassVar[SettingsConfigDict] = {'arbitrary_types_allowed': True, 'case_sensitive': True, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_kebab_case': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_shortcuts': None, 'cli_use_class_docs_for_groups': False, 'enable_decoding': True, 'env_file': '.env', 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': None, 'env_nested_max_split': None, 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': '', 'extra': 'allow', 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_validate', 'model_dump', 'settings_customise_sources'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_config_section': None, 'yaml_file': None, 'yaml_file_encoding': None}#
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- get_config()[source]#
Get the global Axioms configuration instance.
- Returns:
The configuration instance.
- Return type:
- Raises:
RuntimeError – If configuration has not been initialized.
- set_config(config)[source]#
Set the global Axioms configuration instance.
- Parameters:
config (AxiomsConfig) – The AxiomsConfig instance to use globally.
- Return type:
None
- init_axioms(app=None, **kwargs)[source]#
Initialize Axioms configuration for a FastAPI application.
- Parameters:
app – Optional FastAPI application instance.
**kwargs – Configuration parameters to override environment variables.
- Returns:
The initialized configuration.
- Return type:
Example:
from fastapi import FastAPI from axioms_fastapi import init_axioms app = FastAPI() config = init_axioms( app, AXIOMS_AUDIENCE="api.example.com", AXIOMS_DOMAIN="auth.example.com" )