Metadata-Version: 2.4
Name: auth-guardian
Version: 0.1.21
Summary: Libreria de autenticacion OIDC con Keycloak para FastAPI
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: httpx<0.29,>=0.28
Requires-Dist: python-jose[cryptography]<4,>=3.5
Provides-Extra: database
Requires-Dist: sqlalchemy<3,>=2.0; extra == "database"
Requires-Dist: aiosqlite<1,>=0.20; extra == "database"
Provides-Extra: fastapi
Requires-Dist: fastapi<0.119,>=0.118; extra == "fastapi"
Provides-Extra: dev
Requires-Dist: build<2,>=1.3; extra == "dev"
Requires-Dist: fastapi<0.119,>=0.118; extra == "dev"
Requires-Dist: mypy<2,>=1.10; extra == "dev"
Requires-Dist: pytest<9,>=8.3; extra == "dev"
Requires-Dist: pytest-asyncio<2,>=1.2; extra == "dev"
Requires-Dist: respx<0.23,>=0.22; extra == "dev"
Requires-Dist: ruff<0.15,>=0.14; extra == "dev"
Requires-Dist: twine<7,>=6.2; extra == "dev"

# Auth Guardian

<p align="center">
  <img src="https://img.shields.io/pypi/v/auth-guardian?color=blue&label=PyPI" alt="PyPI version"/>
  <img src="https://img.shields.io/pypi/pyversions/auth-guardian" alt="Python versions"/>
  <img src="https://img.shields.io/pypi/l/auth-guardian" alt="License"/>
</p>

> Librería para integrar FastAPI con Keycloak sin complicarte con OIDC desde cero.

---

## ¿Para qué sirve?

Con `auth-guardian` tienes listo:

- Login OIDC con Keycloak.
- Rutas `/login`, `/oidc/callback` y `/logout`.
- Protección de endpoints autenticados.
- Protección por rol (`admin`, etc.).
- Validación en tiempo real por introspection.
- Logout con revocación inmediata del refresh token.

---

## Instalación

```bash
pip install auth-guardian
```

**Requisitos:** Python >= 3.10

---

## Configuración rápida

### 1. Variables de entorno obligatorias

La librería **falla al iniciar con un mensaje claro** si falta alguna de estas:

```env
KEYCLOAK_BASE_URL=
KEYCLOAK_REALM=
KEYCLOAK_CLIENT_ID=
KEYCLOAK_CLIENT_SECRET=
```

> `KEYCLOAK_CLIENT_SECRET` se usa tanto para introspection como para firmar/verificar el `state` anti-CSRF.

### 2. Configuración en Keycloak

Antes de arrancar, verifica que tu cliente en Keycloak esté configurado correctamente:

1. Crear cliente de tipo **OIDC**.
2. Activar **Client authentication** (cliente confidencial).
3. Configurar el **Client Secret**.
4. Agregar la **Redirect URI** de tu app para el callback OIDC.
5. Asignar **roles** en realm o client según tu modelo de autorización.

---

## Integración con FastAPI

La forma más simple:

1. Copia el archivo de ejemplo:
   - `examples/auth.py`
2. Levántalo:

```bash
uvicorn examples.auth:app --reload
```

Ese ejemplo ya trae todo:

- login
- callback
- logout
- endpoint protegido (`/perfil`)
- endpoint por rol (`/admin`)
- registro opcional (`/register`)

Si quieres activar `/register`, agrega:

```env
AUTH_ENABLE_REGISTER=true
KEYCLOAK_ADMIN_CLIENT_ID=
KEYCLOAK_ADMIN_CLIENT_SECRET=
```

Si prefieres integrarlo manualmente en tu propia app, este es el mínimo:

```python
from fastapi import Depends, FastAPI
from auth_guardian import AuthGuardian, create_auth_router

app = FastAPI()
auth = AuthGuardian()

app.include_router(create_auth_router(auth=auth))

@app.get("/perfil")
async def perfil(user: dict = Depends(auth.get_current_user)):
    return user
```

---

## Flujos de autenticación

### 1. Login OIDC

El usuario accede a `/login` y es redirigido al servidor Keycloak. Una vez que ingresa sus credenciales, Keycloak devuelve un `code` al callback, que la librería intercambia por los tokens.

![Flujo de Login OIDC](https://mermaid.ink/img/c2VxdWVuY2VEaWFncmFtCiAgICBwYXJ0aWNpcGFudCBVIGFzIFVzdWFyaW8KICAgIHBhcnRpY2lwYW50IEEgYXMgQVBJIEZhc3RBUEkKICAgIHBhcnRpY2lwYW50IEsgYXMgS2V5Y2xvYWsKCiAgICBVLT4-QTogR0VUIC9sb2dpbgogICAgQS0-Pks6IFJlZGlyZWN0IEF1dGhvcml6YXRpb24gUmVxdWVzdAogICAgSy0tPj5VOiBMb2dpbiBVSQogICAgVS0-Pks6IENyZWRlbmNpYWxlcwogICAgSy0tPj5BOiBSZWRpcmVjdCAvb2lkYy9jYWxsYmFjaz9jb2RlPS4uLgogICAgQS0-Pks6IEV4Y2hhbmdlIGNvZGUgcG9yIHRva2VucwogICAgSy0tPj5BOiBhY2Nlc3NfdG9rZW4gKyByZWZyZXNoX3Rva2VuCiAgICBBLS0-PlU6IFNldCBjb29raWVzICsgcmVkaXJlY3QgYXBw)

---

### 2. Request protegido (introspection)

En cada request a un endpoint protegido, el token del cliente es validado **en tiempo real** contra Keycloak. No hay caché ni validación local por defecto.

![Flujo de Introspection](https://mermaid.ink/img/c2VxdWVuY2VEaWFncmFtCiAgICBwYXJ0aWNpcGFudCBDIGFzIENsaWVudGUKICAgIHBhcnRpY2lwYW50IEEgYXMgQVBJCiAgICBwYXJ0aWNpcGFudCBLIGFzIEtleWNsb2FrCgogICAgQy0-PkE6IFJlcXVlc3QgY29uIHRva2VuCiAgICBBLT4-SzogUE9TVCAvdG9rZW4vaW50cm9zcGVjdAogICAgSy0tPj5BOiBhY3RpdmU6IHRydWUgIOKGkiAyMDAgT0sKICAgIEstLT4-QTogYWN0aXZlOiBmYWxzZSDihpIgNDAxIFVuYXV0aG9yaXplZA==)

---

### 3. Logout

El logout revoca el refresh token en Keycloak **antes** de borrar las cookies, garantizando que la sesión quede inválida de inmediato en el servidor.

![Flujo de Logout](https://mermaid.ink/img/c2VxdWVuY2VEaWFncmFtCiAgICBwYXJ0aWNpcGFudCBVIGFzIFVzdWFyaW8KICAgIHBhcnRpY2lwYW50IEEgYXMgQVBJCiAgICBwYXJ0aWNpcGFudCBLIGFzIEtleWNsb2FrCgogICAgVS0-PkE6IEdFVCAvbG9nb3V0CiAgICBBLT4-SzogUE9TVCAvcmV2b2tlIChyZWZyZXNoX3Rva2VuKQogICAgSy0tPj5BOiAyMDAvMjA0CiAgICBBLS0-PlU6IERlbGV0ZSBjb29raWVzICsgcmVkaXJlY3Q=)

---

## Validación de token

`AuthGuardian` valida el token en cada request consultando a Keycloak en tiempo real mediante `/token/introspect`.

**Comportamiento ante errores:**

| Situación | Respuesta |
|---|---|
| `active: false` | `401 Unauthorized` |
| Keycloak no disponible | `503 Service Unavailable` (sin exponer detalles internos) |
| API de Keycloak caída | Falla introspection aunque la BD de Keycloak esté activa |

---

## API pública estable

Uso habitual:

- `AuthGuardian`
- `create_auth_router`
- `auth.get_current_user`
- `auth.require_role`

---

## Troubleshooting

### `Missing required configuration variables`

**Causa:** Falta una o más variables de entorno obligatorias.

**Solución:** Completar las cuatro variables en tu `.env`:
```env
KEYCLOAK_BASE_URL=
KEYCLOAK_REALM=
KEYCLOAK_CLIENT_ID=
KEYCLOAK_CLIENT_SECRET=
```

---

### Introspection devuelve 401 o 403

**Causa:** El cliente no está configurado como confidencial en Keycloak, o el secret es incorrecto.

**Solución:**
- Verificar `KEYCLOAK_CLIENT_SECRET` en tu `.env`.
- Confirmar que el cliente tiene **Client authentication** activado en Keycloak.

---

### Login falla en callback (Redirect URI mismatch)

**Causa:** La Redirect URI configurada en Keycloak no coincide con la que usa la app.

**Solución:**
- Revisar la **Valid Redirect URIs** del cliente en Keycloak.
- Si estás detrás de un proxy inverso, verificar que se pasen correctamente las cabeceras `Host` y `X-Forwarded-*`.
