Skip to main content

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.

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.


💡 Core Examples: Why You Should Use It

1. The Direct Approach (FastAPI Dependency)

Validate a token in FastAPI without letting the JWT library block your event loop with hidden network calls.

from fastapi import FastAPI, Depends, HTTPException, Request
from async_jwt_core import Validator, ValidationError

app = FastAPI()
validator = Validator(algorithms=["RS256"])

@app.get("/protected")
async def protected_route(request: Request):
    try:
        # Extract token from request headers
        token = Validator.extract_token(request)
        
        # YOU fetch the keys (e.g., from Redis). No hidden I/O!
        jwks = await my_custom_key_fetcher() 
        
        # Validate!
        claims = await validator.validate(token, jwks)
        return {"message": f"Welcome {claims.sub}!"}
        
    except ValidationError as e:
        raise HTTPException(status_code=401, detail=str(e))

2. The Middleware Approach (FastAPI)

Just like you add CORSMiddleware, you can add our FastAPIMiddleware to protect all routes automatically!

from fastapi import FastAPI
from async_jwt_core import Validator
from async_jwt_core.middleware import FastAPIMiddleware

app = FastAPI()

# 1. Initialize validator (Uses ASYNC_JWT_ISSUER from ENV)
validator = Validator(algorithms=["RS256"])

# 2. Add middleware just like CORSMiddleware!
app.add_middleware(
    FastAPIMiddleware,
    validator=validator,
    jwks={"keys": [...]} # Pass your JWKS here
)

@app.get("/protected")
async def protected_route(request: Request):
    # Claims are automatically attached to request.state!
    claims = request.state.user_claims
    return {"message": f"Hello {claims.sub}"}

🏆 Feature Showcase: Why We Are the Best

Here is a comparison of why async-jwt-core is the ultimate choice for modern Python web applications:

Feature / Capability Standard PyJWT Framework Libs async-jwt-core
Async Native ❌ (Sync only) 🟡 (Sometimes) ✅
Zero I/O (Absolute Control) ✅ ❌ (Often fetches keys) ✅
No Framework Lock-in ✅ ❌ (FastAPI/Django only) ✅
Extensible Algorithms ❌ (Hard to add) ❌ (Hard to add) ✅
In-built Middlewares ❌ ❌ ✅ (FastAPI, Flask, Django)
In-built Rate Limiting ❌ ❌ ✅ (Token Bucket)
JWE Decryption ❌ ❌ ✅ (RSA-OAEP + AES-GCM)
Token Creation (Signing) ✅ ❌ ✅
Role & Scope Validation (RBAC) ❌ (Do it yourself) ❌ (Do it yourself) ✅
Access IDs Validation ❌ (Do it yourself) ❌ (Do it yourself) ✅
Session ID Validation ❌ (Do it yourself) ❌ (Do it yourself) ✅

🌍 Environment Variables Configuration

You can configure the default behavior of the Validator using environment variables. This is useful for containerized applications and avoiding hardcoded secrets in code.

All variables use the ASYNC_JWT_ prefix to avoid conflicts:

Variable Description Default Example
ASYNC_JWT_ALGORITHMS Comma-separated list of allowed algorithms. RS256 RS256,HS256
ASYNC_JWT_ISSUER The expected issuer (iss) claim. None https://auth.example.com
ASYNC_JWT_AUDIENCE The expected audience (aud) claim. None my-api-audience

How to use them:

Just set them in your OS or .env file:

export ASYNC_JWT_ALGORITHMS="RS256,HS256"
export ASYNC_JWT_ISSUER="https://auth.yourdomain.com"
export ASYNC_JWT_AUDIENCE="your-app-audience"

And initialize the validator without arguments:

from async_jwt_core import Validator

# Automatically picks up values from the environment variables!
validator = Validator()

✨ Key Features

  • 🔒 Zero Network I/O – Keys are fetched externally.
  • ⚡ Async-Only API – Designed from the ground up for asyncio.
  • 🧩 Framework Agnostic – Works with FastAPI, Sanic, aiohttp, Flask, or Django.
  • 🎯 Custom Claim Validation – Pass your own validation functions.
  • 📦 Ultra Lightweight – Only depends on cryptography.

🔐 Supported Algorithms

We support a vast range of modern cryptographic algorithms out of the box (13 total): HS256, HS384, HS512, RS256, RS384, RS512, PS256, PS384, PS512, ES256, ES384, ES512, EdDSA.


🔬 How to Test Your Application

Testing an application that uses async-jwt-core is easy. You can mock the Validator or create valid tokens for testing using Encoder.

Here is an example using pytest and httpx to test a FastAPI endpoint:

import pytest
from httpx import AsyncClient
from async_jwt_core import Encoder

@pytest.mark.asyncio
async def test_protected_route():
    from my_app import app # Import your FastAPI app
    
    # 1. Create a valid token for testing
    header = {"alg": "HS256", "kid": "test-key"}
    payload = {"sub": "user123", "roles": ["admin"]}
    secret = "my-test-secret"
    
    token = Encoder.create_token(header, payload, secret)
    
    # 2. Call your protected endpoint
    async with AsyncClient(app=app, base_url="http://test") as ac:
        response = await ac.get(
            "/protected",
            headers={"Authorization": f"Bearer {token}"}
        )
        
    assert response.status_code == 200
    assert response.json()["message"] == "Welcome user123!"

📖 Examples (References for Users)

We provide full working examples in the GitHub repository:


🛠️ Installation

uv add async-jwt-core

🔗 Project Links & Resources

🤝 Contributing

We welcome contributions! This is an open-source project designed to make async JWT validation better for everyone. If you have ideas for new features, bug fixes, or improvements, feel free to open an issue or submit a pull request on GitHub!

👤 Author

Developed and maintained by Bishwajit Garai.


📄 License

MIT

Metadata

Release files for async-jwt-core 0.2.9

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for async-jwt-core 0.2.9
File Size Uploaded
async_jwt_core-0.2.9.tar.gz 17.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for async-jwt-core 0.2.9
File Interpreter ABI Platform
async_jwt_core-0.2.9-py3-none-any.whl Python 3 none any Details

Total release size: 37.0 kB

Release files / async_jwt_core-0.2.9.tar.gz

Download URL async_jwt_core-0.2.9.tar.gz
Size 17.0 kB
Tags Source
SHA-256 checksum
How to use checksums
5f53c984d44b3200d078ebfef0b92f2e502fde90fc7c0d30b29b39e07fe79d63
BLAKE2b-256 checksum
How to use checksums
6df4d7feeaa5116618d4158dd41dfe47bfea34ecda24fbbd14b06cbf4ffdc0fa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.13

Release files / async_jwt_core-0.2.9-py3-none-any.whl

Download URL async_jwt_core-0.2.9-py3-none-any.whl
Size 20.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
91e7913105526b2f997c52b93299b00f5aef79f15c286262ab284fb29792a7fc
BLAKE2b-256 checksum
How to use checksums
3aaf93cef765dcfcce91245913312c6c3c0693adf001510313c514910148f566
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.13

Release history Release notifications | RSS feed

This release

0.2.9 This release

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.6

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page