# 🔐 Auth Middleware
[](https://badge.fury.io/py/auth-middleware)
[](https://www.python.org/downloads/)
[](https://opensource.org/licenses/MIT)
[](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[](https://badge.fury.io/py/auth-middleware)\n[](https://www.python.org/downloads/)\n[](https://opensource.org/licenses/MIT)\n[](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"
}