Skip to main content

Async Auth Middleware for FastAPI/Starlette

Project description

Auth Middleware

PyPI version Python 3.14+ License: MIT Coverage

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.

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Links

Credits

Created by impalah


Made for modern Python async applications

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

auth_middleware-0.4.2.tar.gz (8.9 MB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

auth_middleware-0.4.2-py3-none-any.whl (70.7 kB view details)

Uploaded Python 3

File details

Details for the file auth_middleware-0.4.2.tar.gz.

File metadata

  • Download URL: auth_middleware-0.4.2.tar.gz
  • Upload date:
  • Size: 8.9 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","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

Hashes for auth_middleware-0.4.2.tar.gz
Algorithm Hash digest
SHA256 c14e619f1c884314a96b5c6d51da40348d269caae286b11ef06584e20ca7f4da
MD5 ab621164ab5dcada09e65c712308c741
BLAKE2b-256 95b0fbbe74e7e20a95383d355d58c1f348735676b154f1bcc4c3aa1e381d2422

See more details on using hashes here.

File details

Details for the file auth_middleware-0.4.2-py3-none-any.whl.

File metadata

  • Download URL: auth_middleware-0.4.2-py3-none-any.whl
  • Upload date:
  • Size: 70.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.8 {"installer":{"name":"uv","version":"0.11.8","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

Hashes for auth_middleware-0.4.2-py3-none-any.whl
Algorithm Hash digest
SHA256 74f95e248dcd27497a12811e9e6918a50f158e53ed1cd0e6018f5dafcae73be4
MD5 896130163b72d815dbbb66858694e523
BLAKE2b-256 84ab30c9bfb95434f0072e86d1becf8a85c2a8f2b1ebb3b1294f8aa0a3ebaa32

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page