Metadata-Version: 2.4
Name: async-jwt-core
Version: 0.2.5
Summary: A minimal, spec-first, framework-agnostic, async-only JWT validator with zero network dependencies.
Author: Bishwajit Garai
License: MIT
Requires-Python: >=3.11
Requires-Dist: cryptography>=48.0.0
Description-Content-Type: text/markdown

# async-jwt-core

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

[![PyPI version](https://img.shields.io/pypi/v/async-jwt-core.svg)](https://pypi.org/project/async-jwt-core/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

- **PyPI**: https://pypi.org/project/async-jwt-core/
- **GitHub**: https://github.com/Bishwajitgarai/async-jwt-core

---

## 🚀 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.

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

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

---

## ✨ 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 (12 total):

| Type | Algorithms |
| :--- | :--- |
| **HMAC** (Symmetric) | `HS256`, `HS384`, `HS512` |
| **RSA** (Asymmetric) | `RS256`, `RS384`, `RS512` |
| **RSA-PSS** (Asymmetric)| `PS256`, `PS384`, `PS512` |
| **ECDSA** (Elliptic Curve)| `ES256`, `ES384`, `ES512` |

## 🌟 Extra Features to Help You (35+ Features Total)

### 1. Built-in Framework Middlewares
We now include ready-to-use middlewares for popular frameworks: `FastAPIMiddleware`, `FlaskMiddleware`, and `DjangoMiddleware`.

### 2. Unique Environment Variable Configuration
We use unique, non-conflicting environment variables to load defaults: `ASYNC_JWT_ALGORITHMS`, `ASYNC_JWT_ISSUER`, `ASYNC_JWT_AUDIENCE`.

### 3. Token Creation (Signing)
We are no longer just a validator! You can now create and sign tokens easily using `Encoder.create_token()`.

## 📖 Examples (References for Users)

We provide full working examples in the GitHub repository:

-   📄 **[Basic Usage](https://github.com/Bishwajitgarai/async-jwt-core/blob/main/examples/basic_usage.py)**: Shows how to create and validate a token.
-   🚀 **[FastAPI Demo](https://github.com/Bishwajitgarai/async-jwt-core/blob/main/examples/fastapi_demo.py)**: Shows how to integrate with FastAPI.
-   🌶️ **[Flask Demo](https://github.com/Bishwajitgarai/async-jwt-core/blob/main/examples/flask_demo.py)**: Shows how to use it in Flask.
-   🎸 **[Django Demo](https://github.com/Bishwajitgarai/async-jwt-core/blob/main/examples/django_demo.py)**: Shows how to use it in Django.

## 🛠️ Installation

```bash
uv add async-jwt-core
```

## 📄 License

MIT
