Libreria de autenticacion OIDC con Keycloak para FastAPI
Project description
Auth Guardian
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/callbacky/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
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:
KEYCLOAK_BASE_URL=
KEYCLOAK_REALM=
KEYCLOAK_CLIENT_ID=
KEYCLOAK_CLIENT_SECRET=
KEYCLOAK_CLIENT_SECRETse usa tanto para introspection como para firmar/verificar elstateanti-CSRF.
2. Configuración en Keycloak
Antes de arrancar, verifica que tu cliente en Keycloak esté configurado correctamente:
- Crear cliente de tipo OIDC.
- Activar Client authentication (cliente confidencial).
- Configurar el Client Secret.
- Agregar la Redirect URI de tu app para el callback OIDC.
- Asignar roles en realm o client según tu modelo de autorización.
Integración con FastAPI
Crea un archivo auth.py y pega esto:
from __future__ import annotations
import os
from typing import Any
from fastapi import Depends, FastAPI, HTTPException, status
from pydantic import BaseModel, Field
from auth_guardian import AuthGuardian, KeycloakAPIError, create_auth_router
AUTH_ENABLE_REGISTER = os.getenv("AUTH_ENABLE_REGISTER", "false").lower() == "true"
KEYCLOAK_ADMIN_CLIENT_ID = os.getenv("KEYCLOAK_ADMIN_CLIENT_ID", "")
KEYCLOAK_ADMIN_CLIENT_SECRET = os.getenv("KEYCLOAK_ADMIN_CLIENT_SECRET", "")
app = FastAPI(title="AuthGuardian Demo")
auth = AuthGuardian()
app.include_router(
create_auth_router(
auth=auth,
login_redirect_url="/perfil",
logout_redirect_url="/login",
)
)
class RegisterRequest(BaseModel):
username: str = Field(min_length=3, max_length=64)
email: str = Field(min_length=5, max_length=128)
password: str = Field(min_length=8, max_length=128)
first_name: str = ""
last_name: str = ""
@app.get("/health")
async def health() -> dict[str, str]:
return {"status": "ok"}
@app.get("/perfil")
async def perfil(user: dict[str, Any] = Depends(auth.get_current_user)) -> dict[str, Any]:
return {
"mensaje": f"Hola {user.get('preferred_username')}",
"email": user.get("email"),
"sub": user.get("sub"),
}
@app.get("/admin")
async def admin(user: dict[str, Any] = Depends(auth.require_role("admin"))) -> dict[str, str]:
return {"mensaje": "Acceso permitido para rol admin"}
if AUTH_ENABLE_REGISTER:
@app.post("/register", status_code=status.HTTP_201_CREATED)
async def register(payload: RegisterRequest) -> dict[str, Any]:
if not KEYCLOAK_ADMIN_CLIENT_ID or not KEYCLOAK_ADMIN_CLIENT_SECRET:
raise HTTPException(
status_code=500,
detail=(
"Faltan variables para /register: "
"KEYCLOAK_ADMIN_CLIENT_ID y KEYCLOAK_ADMIN_CLIENT_SECRET"
),
)
try:
user = await auth.oidc_client.create_user_via_admin_api(
admin_client_id=KEYCLOAK_ADMIN_CLIENT_ID,
admin_client_secret=KEYCLOAK_ADMIN_CLIENT_SECRET,
username=payload.username,
email=payload.email,
first_name=payload.first_name,
last_name=payload.last_name,
password=payload.password,
enabled=True,
email_verified=False,
)
except KeycloakAPIError as exc:
raise HTTPException(status_code=exc.status_code, detail=exc.detail) from exc
return {"mensaje": "Usuario creado correctamente", "usuario": user}
Levanta la app:
uvicorn auth:app --reload
Si quieres habilitar /register, agrega:
AUTH_ENABLE_REGISTER=true
KEYCLOAK_ADMIN_CLIENT_ID=
KEYCLOAK_ADMIN_CLIENT_SECRET=
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.
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.
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.
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:
AuthGuardiancreate_auth_routerauth.get_current_userauth.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:
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_SECRETen 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
HostyX-Forwarded-*.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file auth_guardian-0.1.22.tar.gz.
File metadata
- Download URL: auth_guardian-0.1.22.tar.gz
- Upload date:
- Size: 24.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54e56345f2c9ae3b99ce1569d42eb93a655a89d19a9d8ff51923fedcf182b2a0
|
|
| MD5 |
538cd01f47190a8f8733a0db1fc642b5
|
|
| BLAKE2b-256 |
20fcb735465e4365b9dc0230a342fe55db2cb7274a69b8dd3dcfadfefba0db54
|
File details
Details for the file auth_guardian-0.1.22-py3-none-any.whl.
File metadata
- Download URL: auth_guardian-0.1.22-py3-none-any.whl
- Upload date:
- Size: 22.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c331183789baebd76ee5f9406115a4cb5812a5c4302762b2d918e04cd824f0b4
|
|
| MD5 |
a0d18de39d80e95b896f291d0aa3f177
|
|
| BLAKE2b-256 |
3dad9afe156bbef755fd5510329293810a37a53926ee7c17313bb68926b7a87a
|