Skip to main content

A minimal, spec-first, framework-agnostic, async-only JWT validator with zero network dependencies.

Project description

async-jwt-core

A minimal, spec-first, framework-agnostic, async-only JWT validator with zero network dependencies.

PyPI version License: MIT


🚀 Why async-jwt-core? (The Problem We Solve)

In the modern Python async ecosystem, validating JWTs using JSON Web Key Sets (JWKS) usually forces you into one of two bad situations:

  1. Framework Lock-in: Libraries tied directly to FastAPI, Starlette, or Django.
  2. Opinionated I/O: Libraries that insist on making network calls for you (often using specific HTTP clients) to fetch keys, making it hard to implement custom caching (like Redis) or use your own HTTP session.

async-jwt-core solves this by doing exactly one thing perfectly: Pure Cryptographic Validation without I/O.

We provide the core validation logic. You bring the keys. This gives you absolute control over how keys are fetched, cached, and stored, while ensuring your event loop never blocks.

✨ Key Features

  • 🔒 Zero Network I/O – Keys are fetched externally. The validator only does the heavy lifting (crypto and claim checks).
  • Async-Only API – Designed from the ground up for asyncio.
  • 🧩 Framework Agnostic – Works with FastAPI, Sanic, aiohttp, or even pure Python background workers.
  • 🛠️ Highly Modular & Extensible – Want to add a custom algorithm? Just inherit from Algorithm and register it.
  • 🎯 Custom Claim Validation – Pass your own validation functions to enforce business rules during the validation phase.
  • 📦 Ultra Lightweight – Only depends on cryptography for secure signature verification.

🛠️ Installation

uv add async-jwt-core
# or
pip install async-jwt-core

📖 Usage Examples

1. The Standard Use Case (With External Fetching)

Here is how you use it in an async environment where you control the I/O:

import asyncio
import aiohttp
from async_jwt_core import Validator, ValidationError

# Initialize once
validator = Validator(
    algorithms=["RS256"],
    issuer="https://auth.example.com",
    audience="api.example.com"
)

async def fetch_jwks(url: str) -> dict:
    """Developer controls all network calls and caching."""
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            return await resp.json()

async def authenticate(token: str):
    # Fetch keys (ideally you'd cache this in Redis or memory)
    jwks = await fetch_jwks("https://auth.example.com/.well-known/jwks.json")
    
    try:
        # Pure async validation
        claims = await validator.validate(token, jwks)
        print(f"Authenticated user: {claims.sub}")
        return claims
    except ValidationError as e:
        print(f"Auth failed: {e}")
        return None

2. Advanced: Custom Claim Validation

Ensure your users have the right roles right during the validation step:

def validate_is_admin(payload: dict) -> bool:
    return "admin" in payload.get("roles", [])

validator = Validator(
    algorithms=["RS256"],
    custom_validators={"is_admin": validate_is_admin}
)

⚖️ Why We Are Better

Feature Standard PyJWT Framework Libs async-jwt-core
Async Native ❌ (Sync only) (Sometimes)
Zero I/O ❌ (Often fetches keys)
No Lock-in ❌ (FastAPI/Django only)
Extensible Algs ❌ (Hard to add) ❌ (Hard to add)

🤝 Contributing

We built this for the community! If you want to add support for more algorithms (like EdDSA or ES256) or improve the claims system, check out our modular folder structure in src/async_jwt_core/algorithms/. It is designed to be easy to extend.

📄 License

MIT

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

async_jwt_core-0.2.0.tar.gz (7.9 kB view details)

Uploaded Source

Built Distribution

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

async_jwt_core-0.2.0-py3-none-any.whl (9.6 kB view details)

Uploaded Python 3

File details

Details for the file async_jwt_core-0.2.0.tar.gz.

File metadata

  • Download URL: async_jwt_core-0.2.0.tar.gz
  • Upload date:
  • Size: 7.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.13

File hashes

Hashes for async_jwt_core-0.2.0.tar.gz
Algorithm Hash digest
SHA256 634b4a4c70adfce3be39a6d6d1118f3af80b242564d22d8b6f5d932b91121da2
MD5 8da6fb1c7821399bed4416918f7872be
BLAKE2b-256 b9ffbb63625aa1971938c7efc0a49b2efa69e584b965c6e435bbd149b5d5a8e9

See more details on using hashes here.

File details

Details for the file async_jwt_core-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: async_jwt_core-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 9.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.13

File hashes

Hashes for async_jwt_core-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 827455a9b3f195366b5dc65ceadcc279f081cdbca234feb61da7b76620d57347
MD5 9a4c5822d3cca39fe9501702e4819de8
BLAKE2b-256 7a75c1c2a6aed05f37588982aa257e568deca05bc605f1fbb4d4e0f6c4402b96

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