Metadata-Version: 2.4
Name: fastapi-auth-client
Version: 0.1.0
Summary: RS256 JWT auth client for FastAPI services — validate tokens via public key / JWKS, no database needed
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: fastapi>=0.110.0
Requires-Dist: python-jose[cryptography]>=3.5.0
Requires-Dist: httpx>=0.27.0

# FastAPI Auth Client

RS256 JWT auth client for FastAPI services. **No database, no Redis, no SMTP.**

Validates JWT tokens **locally** using the RSA public key obtained from the auth service's JWKS endpoint — no shared secret, no network call on every request.

## Install

```bash
pip install fastapi-auth-client
```

## Usage

```python
from fastapi import FastAPI, Depends
from fastapi_auth_client import AuthClient

app = FastAPI()

auth = AuthClient(
    jwks_url="http://auth:8080/.well-known/jwks.json",
    # Or provide the public key directly:
    # jwt_public_key="-----BEGIN PUBLIC KEY-----\nMIIB...\n-----END PUBLIC KEY-----",
)

# Protect any route
@app.get("/api/data")
def get_data(user=Depends(auth.require_user)):
    return {"user": user["sub"], "role": user["role"]}

@app.get("/api/admin")
def admin_only(user=Depends(auth.require_admin)):
    return {"admin": user["sub"]}

# Optional: for guests and authenticated users alike
@app.get("/api/public")
def public_route(user=Depends(auth.optional_user)):
    if user:
        return {"message": f"Hello {user['sub']}"}
    return {"message": "Hello guest"}
```

## How it works

- The auth service signs JWTs with an **RSA private key** (RS256).
- This client verifies them with the corresponding **public key**, fetched from the auth service's `/.well-known/jwks.json` endpoint.
- No shared secret, no database connection, no Redis — zero infrastructure.
- JWKS response is cached (default: 1 hour) to avoid fetching on every request.

## Optional: Real-time revocation

For endpoints that need immediate token revocation checks, enable introspection:

```python
auth = AuthClient(
    jwks_url="http://auth:8080/.well-known/jwks.json",
    auth_service_url="http://auth:8080",
    enable_introspection=True,  # calls /api/auth/introspect on every request
)
```

## Token payload

The `user` dict contains:
- `sub` — username
- `uid` — user_id
- `role` — "user" or "admin"
- `token_type` — "access"
- `token_ver` — token version (used for revocation)
- `jti` — unique token ID
- `exp` — expiry timestamp

## 发布到 PyPI

PyPI 账号和 API Token 由项目 Owner 保管。

### 首次发布

```bash
# 安装发布工具
pip install build twine

# 构建
python -m build

# 上传（输入 username: __token__，password: 你的 API Token）
python -m twine upload dist/*
```

以后更新代码后重复 `python -m build && python -m twine upload dist/*` 即可。

### 版本管理

- `0.1.0` — 初始版本
- `0.1.1` — bug 修复
- `0.2.0` — 新增功能
- `1.0.0` — 稳定版
