Async Auth Middleware for FastAPI/Starlette
Project description
Auth Middleware
Async Authentication and Authorization Middleware for FastAPI/Starlette Applications
Auth Middleware is a comprehensive, production-ready authentication and authorization solution for FastAPI and Starlette applications. It provides a pluggable architecture that supports multiple identity providers and authorization backends with async-first design principles.
Features
Authentication Providers
- AWS Cognito - Full integration with Amazon Cognito User Pools
- Azure Entra ID - Microsoft Azure Active Directory authentication
- Generic JWT - Support for any JWT-based identity provider
- Custom Providers - Extensible architecture for custom authentication
Authorization & Access Control
- Group-based Authorization - Role-based access control with user groups
- Permission-based Authorization - Fine-grained permission system
- SQL Backend Support - PostgreSQL and MySQL for groups/permissions storage
- Cognito Groups Integration - Direct integration with AWS Cognito groups
- Custom Authorization Providers - Build your own authorization logic
Performance & Reliability
- Async-First Design - Built for high-performance async applications
- JWKS Caching - Intelligent caching of JSON Web Key Sets
- Connection Pooling - Efficient database and HTTP connections
- Lazy Loading - User groups and permissions loaded on-demand
- Error Resilience - Graceful degradation on provider failures
Developer Experience
- Type-Safe - Full TypeScript-style type hints throughout
- FastAPI Integration - Native dependency injection support
- Middleware Pattern - Standard ASGI middleware implementation
- Environment Configuration - 12-factor app configuration support
- Comprehensive Documentation - Detailed guides and API reference
Installation
Using pip
pip install auth-middleware
Using poetry
poetry add auth-middleware
Using uv (recommended)
uv add auth-middleware
Quick Start
Basic FastAPI Setup
from fastapi import FastAPI, Depends, Request
from auth_middleware import JwtAuthMiddleware
from auth_middleware.functions import require_user, require_groups
from auth_middleware.providers.authn.cognito_provider import CognitoProvider
from auth_middleware.providers.authn.cognito_authz_provider_settings import CognitoAuthzProviderSettings
app = FastAPI()
# Configure authentication provider
auth_settings = CognitoAuthzProviderSettings(
user_pool_id="us-east-1_abcdef123",
user_pool_region="us-east-1",
jwt_token_verification_disabled=False,
)
# Add authentication middleware
app.add_middleware(
JwtAuthMiddleware,
auth_provider=CognitoProvider(settings=auth_settings),
)
# Protected endpoint - requires valid authentication
@app.get("/protected", dependencies=[Depends(require_user())])
async def protected_endpoint(request: Request):
user = request.state.current_user
return {
"message": f"Hello {user.name}",
"user_id": user.id,
"email": user.email
}
# Role-based endpoint - requires specific groups
@app.get("/admin", dependencies=[Depends(require_groups(["admin", "moderator"]))])
async def admin_endpoint(request: Request):
user = request.state.current_user
groups = await user.groups
return {
"message": "Admin access granted",
"user_groups": groups
}
Azure Entra ID Setup
from auth_middleware.providers.authn.entra_id_provider import EntraIdProvider
from auth_middleware.providers.authn.entra_id_provider_settings import EntraIdProviderSettings
# Configure Azure Entra ID
entra_settings = EntraIdProviderSettings(
tenant_id="your-tenant-id",
client_id="your-client-id",
issuer="https://sts.windows.net/your-tenant-id/",
)
app.add_middleware(
JwtAuthMiddleware,
auth_provider=EntraIdProvider(settings=entra_settings),
)
Generic JWT Provider
from auth_middleware.providers.authn.jwt_provider import JWTProvider
from auth_middleware.providers.authn.jwt_provider_settings import JWTProviderSettings
# Configure generic JWT provider
jwt_settings = JWTProviderSettings(
secret_key="your-secret-key",
algorithm="HS256",
issuer="your-issuer",
)
app.add_middleware(
JwtAuthMiddleware,
auth_provider=JWTProvider(settings=jwt_settings),
)
Configuration
Environment Variables
Configure the middleware using environment variables:
# Core middleware settings
AUTH_MIDDLEWARE_DISABLED=false
AUTH_MIDDLEWARE_LOG_LEVEL=INFO
# JWKS caching configuration
AUTH_MIDDLEWARE_JWKS_CACHE_INTERVAL_MINUTES=20
AUTH_MIDDLEWARE_JWKS_CACHE_USAGES=1000
# AWS Cognito settings (if using Cognito provider)
COGNITO_USER_POOL_ID=us-east-1_abcdef123
COGNITO_USER_POOL_REGION=us-east-1
# Azure Entra ID settings (if using Entra ID provider)
AZURE_TENANT_ID=your-tenant-id
AZURE_CLIENT_ID=your-client-id
AZURE_CLIENT_SECRET=your-client-secret
# JWT settings (if using generic JWT provider)
JWT_SECRET_KEY=your-secret-key
JWT_ALGORITHM=HS256
JWT_ISSUER=your-issuer
Advanced Configuration with Groups and Permissions
from auth_middleware.providers.authz.sql_groups_provider import SqlGroupsProvider
from auth_middleware.providers.authz.sql_permissions_provider import SqlPermissionsProvider
# Setup with database-backed authorization
auth_provider = CognitoProvider(
settings=auth_settings,
groups_provider=SqlGroupsProvider(),
permissions_provider=SqlPermissionsProvider(),
)
app.add_middleware(JwtAuthMiddleware, auth_provider=auth_provider)
# Use permission-based authorization
from auth_middleware.functions import require_permissions
@app.post("/admin/users", dependencies=[Depends(require_permissions(["user.create", "user.manage"]))])
async def create_user(request: Request):
user = request.state.current_user
permissions = await user.permissions
return {"message": "User creation allowed", "permissions": permissions}
Usage Examples
Making Authenticated Requests
# Get JWT token from your identity provider, then:
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
http://localhost:8000/protected
Accessing User Information
@app.get("/profile")
async def get_profile(request: Request):
user = request.state.current_user
return {
"id": user.id,
"name": user.name,
"email": user.email,
"groups": await user.groups,
"permissions": await user.permissions
}
Custom Authorization Logic
from auth_middleware.functions import require_user
@app.delete("/posts/{post_id}")
async def delete_post(post_id: str, request: Request, _: None = Depends(require_user())):
user = request.state.current_user
post = await get_post(post_id)
# Custom authorization logic
user_groups = await user.groups
if post.owner_id != user.id and "admin" not in user_groups:
raise HTTPException(status_code=403, detail="Not authorized to delete this post")
await delete_post_by_id(post_id)
return {"message": "Post deleted successfully"}
Documentation
Core Components
| Component | Description |
|---|---|
JwtAuthMiddleware |
Main ASGI middleware for request authentication |
JWTProvider |
Abstract base for authentication providers |
GroupsProvider |
Abstract base for group-based authorization |
PermissionsProvider |
Abstract base for permission-based authorization |
User |
Pydantic model representing authenticated users |
User Object Properties
The authenticated user is available in request.state.current_user:
| Property | Type | Description |
|---|---|---|
id |
str |
Unique user identifier from identity provider |
name |
str | None |
User's display name |
email |
EmailStr | None |
User's email address |
groups |
list[str] |
User groups (async property) |
permissions |
list[str] |
User permissions (async property) |
Authorization Functions
| Function | Description |
|---|---|
require_user() |
Ensures user is authenticated |
require_groups(groups) |
Requires user to be in specified groups |
require_permissions(permissions) |
Requires user to have specified permissions |
Architecture
graph TD
A[HTTP Request] --> B[JwtAuthMiddleware]
B --> C[JWTBearerManager]
C --> D[JWT Provider]
D --> E[Token Validation]
E --> F[User Creation]
F --> G[Groups Provider]
F --> H[Permissions Provider]
G --> I[request.state.current_user]
H --> I
Development
Setup Development Environment
# Clone the repository
git clone https://github.com/impalah/auth-middleware.git
cd auth-middleware
# Create virtual environment and install dependencies
make venv
# Run tests
make test
# Run type checking
make type-check
# Run linting
make lint
# Run all quality checks
make check
Build and Release
# Build package
make build
# Publish to PyPI
make publish
# Build Docker image
make docker-build
Contributing
We welcome contributions! Please see our Contributing Guide for details.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
License
This project is licensed under the MIT License - see the LICENSE file for details.
Links
- Documentation: Full documentation and guides
- PyPI Package: https://pypi.org/project/auth-middleware/
- Source Code: https://github.com/impalah/auth-middleware
- Bug Reports: GitHub Issues
Credits
Created by impalah
Made for modern Python async applications
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file auth_middleware-0.3.3.tar.gz.
File metadata
- Download URL: auth_middleware-0.3.3.tar.gz
- Upload date:
- Size: 8.9 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
048cc6ea8176af6030288d97f629ec3f9584bf80515373efc01a3f16b0b54423
|
|
| MD5 |
347bcb4659054e87237b6f64fe650df0
|
|
| BLAKE2b-256 |
217b7d59381cea0cc91ce470d471baa98bb331d257f0f1acd7dbf950017df386
|
File details
Details for the file auth_middleware-0.3.3-py3-none-any.whl.
File metadata
- Download URL: auth_middleware-0.3.3-py3-none-any.whl
- Upload date:
- Size: 58.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2512a0fbda87b42c1181aa674b8cb19e7e1891dac958dd5328fc4108b91b5940
|
|
| MD5 |
cad06c9e60e37a4962f36b319d255973
|
|
| BLAKE2b-256 |
d1391847cff45f859a443afbba8c3e1210207783dc6983fb1957436ea8d5aef9
|