auth-middleware


Nameauth-middleware JSON
Version 0.2.14 PyPI version JSON
download
home_pageNone
SummaryAsync Auth Middleware for FastAPI/Starlette
upload_time2025-08-18 11:54:45
maintainerNone
docs_urlNone
authorNone
requires_python>=3.10
licenseMIT
keywords auth fastapi middleware starlette
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 🔐 Auth Middleware

[![PyPI version](https://badge.fury.io/py/auth-middleware.svg)](https://badge.fury.io/py/auth-middleware)
[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Coverage](https://img.shields.io/badge/coverage-83%25-green.svg)](https://github.com/impalah/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

```bash
pip install auth-middleware
```

### Using poetry

```bash
poetry add auth-middleware
```

### Using uv (recommended)

```bash
uv add auth-middleware
```

## 🚀 Quick Start

### Basic FastAPI Setup

```python
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

```python
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

```python
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:

```bash
# 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

```python
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

```bash
# Get JWT token from your identity provider, then:
curl -H "Authorization: Bearer YOUR_JWT_TOKEN" \
     http://localhost:8000/protected
```

### Accessing User Information

```python
@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

```python
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

```mermaid
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

```bash
# 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

```bash
# Build package
make build

# Publish to PyPI
make publish

# Build Docker image
make docker-build
```

## 🤝 Contributing

We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) 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](LICENSE) file for details.

## 🔗 Links

- **Documentation**: [Full documentation and guides](https://auth-middleware.readthedocs.io/)
- **PyPI Package**: [https://pypi.org/project/auth-middleware/](https://pypi.org/project/auth-middleware/)
- **Source Code**: [https://github.com/impalah/auth-middleware](https://github.com/impalah/auth-middleware)
- **Bug Reports**: [GitHub Issues](https://github.com/impalah/auth-middleware/issues)

## 💫 Credits

Created with ❤️ by [impalah](https://github.com/impalah)

---

**Made for modern Python async applications** 🐍⚡

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "auth-middleware",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.10",
    "maintainer_email": null,
    "keywords": "auth, fastapi, middleware, starlette",
    "author": null,
    "author_email": "impalah <impalah@gmail.com>",
    "download_url": "https://files.pythonhosted.org/packages/f7/7b/68436212a82a3734e2ddd9bf99a43159d74d75b7425ee1dc0627b00bf95c/auth_middleware-0.2.14.tar.gz",
    "platform": null,
    "description": "# \ud83d\udd10 Auth Middleware\n\n[![PyPI version](https://badge.fury.io/py/auth-middleware.svg)](https://badge.fury.io/py/auth-middleware)\n[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Coverage](https://img.shields.io/badge/coverage-83%25-green.svg)](https://github.com/impalah/auth-middleware)\n\n**Async Authentication and Authorization Middleware for FastAPI/Starlette Applications**\n\nAuth 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.\n\n## \u2728 Features\n\n### \ud83d\udd11 **Authentication Providers**\n\n- **AWS Cognito** - Full integration with Amazon Cognito User Pools\n- **Azure Entra ID** - Microsoft Azure Active Directory authentication\n- **Generic JWT** - Support for any JWT-based identity provider\n- **Custom Providers** - Extensible architecture for custom authentication\n\n### \ud83d\udee1\ufe0f **Authorization & Access Control**\n\n- **Group-based Authorization** - Role-based access control with user groups\n- **Permission-based Authorization** - Fine-grained permission system\n- **SQL Backend Support** - PostgreSQL and MySQL for groups/permissions storage\n- **Cognito Groups Integration** - Direct integration with AWS Cognito groups\n- **Custom Authorization Providers** - Build your own authorization logic\n\n### \u26a1 **Performance & Reliability**\n\n- **Async-First Design** - Built for high-performance async applications\n- **JWKS Caching** - Intelligent caching of JSON Web Key Sets\n- **Connection Pooling** - Efficient database and HTTP connections\n- **Lazy Loading** - User groups and permissions loaded on-demand\n- **Error Resilience** - Graceful degradation on provider failures\n\n### \ud83d\udd27 **Developer Experience**\n\n- **Type-Safe** - Full TypeScript-style type hints throughout\n- **FastAPI Integration** - Native dependency injection support\n- **Middleware Pattern** - Standard ASGI middleware implementation\n- **Environment Configuration** - 12-factor app configuration support\n- **Comprehensive Documentation** - Detailed guides and API reference\n\n## \ud83d\udce6 Installation\n\n### Using pip\n\n```bash\npip install auth-middleware\n```\n\n### Using poetry\n\n```bash\npoetry add auth-middleware\n```\n\n### Using uv (recommended)\n\n```bash\nuv add auth-middleware\n```\n\n## \ud83d\ude80 Quick Start\n\n### Basic FastAPI Setup\n\n```python\nfrom fastapi import FastAPI, Depends, Request\nfrom auth_middleware import JwtAuthMiddleware\nfrom auth_middleware.functions import require_user, require_groups\nfrom auth_middleware.providers.authn.cognito_provider import CognitoProvider\nfrom auth_middleware.providers.authn.cognito_authz_provider_settings import CognitoAuthzProviderSettings\n\napp = FastAPI()\n\n# Configure authentication provider\nauth_settings = CognitoAuthzProviderSettings(\n    user_pool_id=\"us-east-1_abcdef123\",\n    user_pool_region=\"us-east-1\",\n    jwt_token_verification_disabled=False,\n)\n\n# Add authentication middleware\napp.add_middleware(\n    JwtAuthMiddleware,\n    auth_provider=CognitoProvider(settings=auth_settings),\n)\n\n# Protected endpoint - requires valid authentication\n@app.get(\"/protected\", dependencies=[Depends(require_user())])\nasync def protected_endpoint(request: Request):\n    user = request.state.current_user\n    return {\n        \"message\": f\"Hello {user.name}\",\n        \"user_id\": user.id,\n        \"email\": user.email\n    }\n\n# Role-based endpoint - requires specific groups\n@app.get(\"/admin\", dependencies=[Depends(require_groups([\"admin\", \"moderator\"]))])\nasync def admin_endpoint(request: Request):\n    user = request.state.current_user\n    groups = await user.groups\n    return {\n        \"message\": \"Admin access granted\",\n        \"user_groups\": groups\n    }\n```\n\n### Azure Entra ID Setup\n\n```python\nfrom auth_middleware.providers.authn.entra_id_provider import EntraIdProvider\nfrom auth_middleware.providers.authn.entra_id_provider_settings import EntraIdProviderSettings\n\n# Configure Azure Entra ID\nentra_settings = EntraIdProviderSettings(\n    tenant_id=\"your-tenant-id\",\n    client_id=\"your-client-id\",\n    issuer=\"https://sts.windows.net/your-tenant-id/\",\n)\n\napp.add_middleware(\n    JwtAuthMiddleware,\n    auth_provider=EntraIdProvider(settings=entra_settings),\n)\n```\n\n### Generic JWT Provider\n\n```python\nfrom auth_middleware.providers.authn.jwt_provider import JWTProvider\nfrom auth_middleware.providers.authn.jwt_provider_settings import JWTProviderSettings\n\n# Configure generic JWT provider\njwt_settings = JWTProviderSettings(\n    secret_key=\"your-secret-key\",\n    algorithm=\"HS256\",\n    issuer=\"your-issuer\",\n)\n\napp.add_middleware(\n    JwtAuthMiddleware,\n    auth_provider=JWTProvider(settings=jwt_settings),\n)\n```\n\n## \ud83d\udd27 Configuration\n\n### Environment Variables\n\nConfigure the middleware using environment variables:\n\n```bash\n# Core middleware settings\nAUTH_MIDDLEWARE_DISABLED=false\nAUTH_MIDDLEWARE_LOG_LEVEL=INFO\n\n# JWKS caching configuration\nAUTH_MIDDLEWARE_JWKS_CACHE_INTERVAL_MINUTES=20\nAUTH_MIDDLEWARE_JWKS_CACHE_USAGES=1000\n\n# AWS Cognito settings (if using Cognito provider)\nCOGNITO_USER_POOL_ID=us-east-1_abcdef123\nCOGNITO_USER_POOL_REGION=us-east-1\n\n# Azure Entra ID settings (if using Entra ID provider)\nAZURE_TENANT_ID=your-tenant-id\nAZURE_CLIENT_ID=your-client-id\nAZURE_CLIENT_SECRET=your-client-secret\n\n# JWT settings (if using generic JWT provider)\nJWT_SECRET_KEY=your-secret-key\nJWT_ALGORITHM=HS256\nJWT_ISSUER=your-issuer\n```\n\n### Advanced Configuration with Groups and Permissions\n\n```python\nfrom auth_middleware.providers.authz.sql_groups_provider import SqlGroupsProvider\nfrom auth_middleware.providers.authz.sql_permissions_provider import SqlPermissionsProvider\n\n# Setup with database-backed authorization\nauth_provider = CognitoProvider(\n    settings=auth_settings,\n    groups_provider=SqlGroupsProvider(),\n    permissions_provider=SqlPermissionsProvider(),\n)\n\napp.add_middleware(JwtAuthMiddleware, auth_provider=auth_provider)\n\n# Use permission-based authorization\nfrom auth_middleware.functions import require_permissions\n\n@app.post(\"/admin/users\", dependencies=[Depends(require_permissions([\"user.create\", \"user.manage\"]))])\nasync def create_user(request: Request):\n    user = request.state.current_user\n    permissions = await user.permissions\n    return {\"message\": \"User creation allowed\", \"permissions\": permissions}\n```\n\n## \ud83c\udfaf Usage Examples\n\n### Making Authenticated Requests\n\n```bash\n# Get JWT token from your identity provider, then:\ncurl -H \"Authorization: Bearer YOUR_JWT_TOKEN\" \\\n     http://localhost:8000/protected\n```\n\n### Accessing User Information\n\n```python\n@app.get(\"/profile\")\nasync def get_profile(request: Request):\n    user = request.state.current_user\n\n    return {\n        \"id\": user.id,\n        \"name\": user.name,\n        \"email\": user.email,\n        \"groups\": await user.groups,\n        \"permissions\": await user.permissions\n    }\n```\n\n### Custom Authorization Logic\n\n```python\nfrom auth_middleware.functions import require_user\n\n@app.delete(\"/posts/{post_id}\")\nasync def delete_post(post_id: str, request: Request, _: None = Depends(require_user())):\n    user = request.state.current_user\n    post = await get_post(post_id)\n\n    # Custom authorization logic\n    user_groups = await user.groups\n    if post.owner_id != user.id and \"admin\" not in user_groups:\n        raise HTTPException(status_code=403, detail=\"Not authorized to delete this post\")\n\n    await delete_post_by_id(post_id)\n    return {\"message\": \"Post deleted successfully\"}\n```\n\n## \ud83d\udcda Documentation\n\n### Core Components\n\n| Component             | Description                                      |\n| --------------------- | ------------------------------------------------ |\n| `JwtAuthMiddleware`   | Main ASGI middleware for request authentication  |\n| `JWTProvider`         | Abstract base for authentication providers       |\n| `GroupsProvider`      | Abstract base for group-based authorization      |\n| `PermissionsProvider` | Abstract base for permission-based authorization |\n| `User`                | Pydantic model representing authenticated users  |\n\n### User Object Properties\n\nThe authenticated user is available in `request.state.current_user`:\n\n| Property      | Type               | Description                                   |\n| ------------- | ------------------ | --------------------------------------------- |\n| `id`          | `str`              | Unique user identifier from identity provider |\n| `name`        | `str \\| None`      | User's display name                           |\n| `email`       | `EmailStr \\| None` | User's email address                          |\n| `groups`      | `list[str]`        | User groups (async property)                  |\n| `permissions` | `list[str]`        | User permissions (async property)             |\n\n### Authorization Functions\n\n| Function                           | Description                                 |\n| ---------------------------------- | ------------------------------------------- |\n| `require_user()`                   | Ensures user is authenticated               |\n| `require_groups(groups)`           | Requires user to be in specified groups     |\n| `require_permissions(permissions)` | Requires user to have specified permissions |\n\n## \ud83c\udfd7\ufe0f Architecture\n\n```mermaid\ngraph TD\n    A[HTTP Request] --> B[JwtAuthMiddleware]\n    B --> C[JWTBearerManager]\n    C --> D[JWT Provider]\n    D --> E[Token Validation]\n    E --> F[User Creation]\n    F --> G[Groups Provider]\n    F --> H[Permissions Provider]\n    G --> I[request.state.current_user]\n    H --> I\n```\n\n## \ud83d\udee0\ufe0f Development\n\n### Setup Development Environment\n\n```bash\n# Clone the repository\ngit clone https://github.com/impalah/auth-middleware.git\ncd auth-middleware\n\n# Create virtual environment and install dependencies\nmake venv\n\n# Run tests\nmake test\n\n# Run type checking\nmake type-check\n\n# Run linting\nmake lint\n\n# Run all quality checks\nmake check\n```\n\n### Build and Release\n\n```bash\n# Build package\nmake build\n\n# Publish to PyPI\nmake publish\n\n# Build Docker image\nmake docker-build\n```\n\n## \ud83e\udd1d Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md) for details.\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\n## \ud83d\udcc4 License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## \ud83d\udd17 Links\n\n- **Documentation**: [Full documentation and guides](https://auth-middleware.readthedocs.io/)\n- **PyPI Package**: [https://pypi.org/project/auth-middleware/](https://pypi.org/project/auth-middleware/)\n- **Source Code**: [https://github.com/impalah/auth-middleware](https://github.com/impalah/auth-middleware)\n- **Bug Reports**: [GitHub Issues](https://github.com/impalah/auth-middleware/issues)\n\n## \ud83d\udcab Credits\n\nCreated with \u2764\ufe0f by [impalah](https://github.com/impalah)\n\n---\n\n**Made for modern Python async applications** \ud83d\udc0d\u26a1\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "Async Auth Middleware for FastAPI/Starlette",
    "version": "0.2.14",
    "project_urls": {
        "Documentation": "https://impalah.github.io/auth-middleware/",
        "Homepage": "https://impalah.github.io/auth-middleware/",
        "Repository": "https://github.com/impalah/auth-middleware",
        "Source": "https://github.com/impalah/auth-middleware"
    },
    "split_keywords": [
        "auth",
        " fastapi",
        " middleware",
        " starlette"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "5eaec6c4b0e82105ece783a5b27e1bc254dd311782adc9707e2bd5ac1515ca39",
                "md5": "71d7d51fe6197d3d3d0871e819c1af17",
                "sha256": "9d31dea38faa2738ba6fabf2ba5892ee2740b259cc6448a247d64b288956e584"
            },
            "downloads": -1,
            "filename": "auth_middleware-0.2.14-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "71d7d51fe6197d3d3d0871e819c1af17",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.10",
            "size": 38798,
            "upload_time": "2025-08-18T11:54:44",
            "upload_time_iso_8601": "2025-08-18T11:54:44.155504Z",
            "url": "https://files.pythonhosted.org/packages/5e/ae/c6c4b0e82105ece783a5b27e1bc254dd311782adc9707e2bd5ac1515ca39/auth_middleware-0.2.14-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "f77b68436212a82a3734e2ddd9bf99a43159d74d75b7425ee1dc0627b00bf95c",
                "md5": "8fb630de84e86afcacac8d601afba17e",
                "sha256": "63af44d0579e7e6d6dcf57ce0205677a1e65266bb6505f034e05bbf7c6ed43bd"
            },
            "downloads": -1,
            "filename": "auth_middleware-0.2.14.tar.gz",
            "has_sig": false,
            "md5_digest": "8fb630de84e86afcacac8d601afba17e",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.10",
            "size": 8540615,
            "upload_time": "2025-08-18T11:54:45",
            "upload_time_iso_8601": "2025-08-18T11:54:45.916562Z",
            "url": "https://files.pythonhosted.org/packages/f7/7b/68436212a82a3734e2ddd9bf99a43159d74d75b7425ee1dc0627b00bf95c/auth_middleware-0.2.14.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-18 11:54:45",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "impalah",
    "github_project": "auth-middleware",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": true,
    "lcname": "auth-middleware"
}
        
Elapsed time: 1.63755s