Metadata-Version: 2.4
Name: iurban-auth
Version: 0.1.0
Summary: SDK de integración con Keycloak para microapps FastAPI de iUrban (validación JWT stateless)
Author-email: iUrban <dev@iurban.es>
Requires-Python: >=3.12
Requires-Dist: fastapi>=0.111
Requires-Dist: httpx>=0.27
Requires-Dist: pydantic-settings>=2.3
Requires-Dist: pydantic>=2.7
Requires-Dist: pyjwt[crypto]>=2.9
Provides-Extra: dev
Requires-Dist: mypy>=1.10; extra == 'dev'
Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
Requires-Dist: pytest>=8; extra == 'dev'
Requires-Dist: ruff>=0.5; extra == 'dev'
Description-Content-Type: text/markdown

# iurban-auth (Python / FastAPI)

SDK de integración con el Keycloak central de iUrban para microapps **FastAPI**.
Implementa el patrón decidido en ADR-001 (addendum 2026-06-06): **validación de JWT
stateless** contra la JWKS de Keycloak — sin llamada en runtime a ningún servicio de auth.

## Idea

```python
from fastapi import FastAPI, Depends
from iurban_auth import current_user, require_roles, CurrentUser

app = FastAPI()

@app.get("/me")
async def me(user: CurrentUser = Depends(current_user)):
    return {"sub": user.sub, "tenant": user.tenant_id, "roles": user.roles}

@app.get("/admin", dependencies=[Depends(require_roles("admin"))])
async def admin_only():
    return {"ok": True}
```

## Config (pydantic-settings, vía env)

| Env | Qué | Ejemplo |
|---|---|---|
| `IURBAN_OIDC_ISSUER` | URL del realm Keycloak | `https://auth.iurban-lab.es/realms/iurban` |
| `IURBAN_OIDC_AUDIENCE` | audience esperado (client_id) | `crm-api` |
| `IURBAN_OIDC_JWKS_TTL` | cache de la JWKS (s) | `3600` |

## Multi-tenant

El claim `tenant_id` (o `tenant`) se expone en `CurrentUser.tenant_id` para casar con la
RLS de Postgres de las microapps (ADR-004). El mapeo claim→roles locales lo hace cada app
(Opción A del ADR-001: Keycloak autentica, la app autoriza).

## Estado

Scaffold. Falta: tests contra un Keycloak de pruebas, manejo de `kid` rotado, y publicación
al índice privado (o install desde git-tag).
