Metadata-Version: 2.4
Name: auth-guardian
Version: 0.1.10
Summary: Reusable Keycloak SDK for auth-service and microservices
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

`auth-guardian` es una libreria Python para integrar autenticacion OIDC con Keycloak en FastAPI, con enfoque de seguridad, revocacion inmediata y configuracion simple.

## Paquete y documentación

- PyPI: https://pypi.org/project/auth-guardian/

## Qué resuelve

- Flujo OIDC (`/login`, `/oidc/callback`, `/logout`) sin implementarlo a mano.
- Proteccion de endpoints autenticados.
- Control de acceso por roles.
- Validacion de access token por introspection contra Keycloak (default).
- Revocacion inmediata en logout (refresh token revoke + invalidacion por introspection).

## Instalación

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

## Variables obligatorias

La libreria falla al iniciar si falta alguna variable requerida y registra un log claro indicando cual falta.

- `KEYCLOAK_BASE_URL`
- `KEYCLOAK_REALM`
- `KEYCLOAK_CLIENT_ID`
- `KEYCLOAK_CLIENT_SECRET`

Ejemplo de `.env` minimo:

```env
KEYCLOAK_BASE_URL=http://localhost:8080
KEYCLOAK_REALM=master
KEYCLOAK_CLIENT_ID=my-app-client
KEYCLOAK_CLIENT_SECRET=tu-secret
```

## Configuración recomendada en Keycloak

Para el cliente que usa la API:

1. Crear cliente OIDC.
2. Activar autenticacion de cliente (`Client authentication` / confidential client).
3. Configurar `Client Secret`.
4. Configurar redirect URI de la app para callback OIDC.
5. Verificar roles en realm/client segun tu modelo de autorizacion.

Nota: `KEYCLOAK_CLIENT_SECRET` se usa para introspection y tambien, por defecto, para firmar/verificar `state` anti-CSRF.

## Integración rápida con FastAPI

```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,
        login_redirect_url="/dashboard",
        logout_redirect_url="/login",
    )
)

@app.get("/health")
async def health() -> dict[str, str]:
    return {"status": "ok"}

@app.get("/ejemplo/v1")
async def ejemplo_v1(user: dict = Depends(auth.get_current_user)):
    return {
        "mensaje": f"Hola {user.get('preferred_username')}",
        "email": user.get("email"),
    }

@app.get("/ejemplo/v2")
async def ejemplo_v2(user: dict = Depends(auth.require_role("admin"))):
    return {"mensaje": "Acceso permitido para rol admin"}
```

Con esto tienes:

- `GET /login`
- `GET /oidc/callback`
- `GET /logout`
- Proteccion por usuario autenticado y por rol.

## Flujo visual (imágenes)

### 1) Login OIDC

```mermaid
sequenceDiagram
    participant U as Usuario
    participant A as API FastAPI
    participant K as Keycloak

    U->>A: GET /login
    A->>K: Redirect Authorization Request
    K-->>U: Login UI
    U->>K: Credenciales
    K-->>A: Redirect /oidc/callback?code=...
    A->>K: Exchange code por tokens
    K-->>A: access_token + refresh_token
    A-->>U: Set cookies + redirect app
```

### 2) Request protegido (introspection)

```mermaid
sequenceDiagram
    participant C as Cliente
    participant A as API
    participant K as Keycloak

    C->>A: Request con token
    A->>K: POST /token/introspect
    K-->>A: { active: true/false }
    alt active=true
        A-->>C: 200 OK
    else active=false
        A-->>C: 401 Unauthorized
    end
```

### 3) Logout

```mermaid
sequenceDiagram
    participant U as Usuario
    participant A as API
    participant K as Keycloak

    U->>A: GET /logout
    A->>K: POST /revoke (refresh_token)
    K-->>A: 200/204
    A-->>U: Delete cookies + redirect
```

## Validación de token

`AuthGuardian` usa introspection por defecto:

| Modo | Comportamiento |
|---|---|
| `introspection` (default) | Valida cada request contra Keycloak (`/token/introspect`) |

Notas operativas:

- Si `active=false`, responde `401`.
- Si Keycloak no está disponible, responde `503` sin filtrar detalles internos.
- Si cae la API de Keycloak, introspection falla aunque la BD de Keycloak siga arriba.

## Troubleshooting

### Falta una variable obligatoria

Síntoma:

- Error al iniciar con mensaje `Missing required configuration variables`.

Accion:

- Completar las variables Keycloak requeridas en entorno.

### Introspection devuelve 401 o 403

Síntoma:

- Error relacionado a introspection denegada.

Accion:

- Verificar `KEYCLOAK_CLIENT_SECRET`.
- Verificar que el cliente en Keycloak tenga autenticacion de cliente habilitada.

### Redirect URI o callback incorrecto

Síntoma:

- Login falla en callback o mismatch en Keycloak.

Accion:

- Revisar la configuracion de redirect URI del cliente en Keycloak.
- Si estas detras de proxy, revisar cabeceras `Host` y `X-Forwarded-*`.

## API pública estable

- `AuthGuardian`
- `create_auth_router`
- `extract_client_roles(payload, client_id)`
- `AuthConfig`
- `AuthTokenValidator`
- `AuthOIDCClient`
- `KeycloakAuthError`
- `TokenValidationError`
- `KeycloakAPIError`
