Libreria de autenticacion OIDC con Keycloak para FastAPI
Project description
Auth Guardian
Librería Python para integrar autenticación OIDC con Keycloak en FastAPI — con foco en seguridad, revocación inmediata y configuración mínima.
¿Qué resuelve?
Sin auth-guardian tendrías que implementar a mano el flujo OIDC completo, la validación de tokens, el manejo de cookies y la revocación en logout. Con esta librería, todo eso queda resuelto en unas pocas líneas:
| Problema | Solución |
|---|---|
| Flujo OIDC completo | Rutas /login, /oidc/callback, /logout listas para usar |
| Protección de endpoints | Depends(auth.get_current_user) |
| Control de acceso por rol | Depends(auth.require_role("admin")) |
| Validación de token en cada request | Introspection contra Keycloak (activo por defecto) |
| Revocación inmediata en logout | Revoke del refresh token + invalidación por introspection |
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=https://auth.tudominio.com
KEYCLOAK_REALM=tu-realm
KEYCLOAK_CLIENT_ID=tu-cliente
KEYCLOAK_CLIENT_SECRET=tu-secreto
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
Setup inicial
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", # A dónde redirige después del login exitoso
logout_redirect_url="/login", # A dónde redirige después del logout
)
)
Esto registra automáticamente tres rutas en tu app:
| Ruta | Método | Qué hace |
|---|---|---|
/login |
GET | Redirige al usuario a la pantalla de login de Keycloak |
/oidc/callback |
GET | Recibe el código de Keycloak, lo intercambia por tokens y guarda las cookies de sesión |
/logout |
GET | Revoca el token en Keycloak, borra las cookies y redirige |
No necesitas implementar ninguna de estas rutas manualmente.
GET /login
El usuario navega a esta ruta (o le pones un botón que apunte a ella). La librería construye la URL de autorización y redirige a Keycloak automáticamente.
# No necesitas definir esta ruta — ya existe gracias a create_auth_router.
# Úsala desde el frontend así:
# <a href="/login">Iniciar sesión</a>
GET /oidc/callback
Keycloak redirige aquí después de que el usuario ingresa sus credenciales. La librería intercambia el code por los tokens y guarda la sesión en cookies. El usuario no interactúa con esta ruta directamente.
# Tampoco defines esta ruta manualmente.
# Solo asegúrate de que la Redirect URI en Keycloak apunte a:
# https://tu-dominio.com/oidc/callback
GET /logout
Revoca el refresh token en Keycloak y limpia las cookies de sesión. Apunta un botón a esta ruta para cerrar la sesión del usuario.
# <a href="/logout">Cerrar sesión</a>
Proteger tus propios endpoints
Una vez que el usuario tiene sesión activa, puedes proteger cualquier endpoint de dos formas:
Por autenticación — solo requiere que el usuario haya hecho login:
@app.get("/perfil")
async def perfil(user: dict = Depends(auth.get_current_user)):
return {
"mensaje": f"Hola {user.get('preferred_username')}",
"email": user.get("email"),
}
Por rol — además del login, verifica que el usuario tenga el rol indicado:
@app.get("/admin")
async def admin(user: dict = Depends(auth.require_role("admin"))):
return {"mensaje": "Acceso permitido solo para rol admin"}
Si el usuario no está autenticado recibe un 401. Si está autenticado pero no tiene el rol, recibe un 403.
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 usa introspection por defecto — cada request verifica el token contra Keycloak en tiempo real.
| Modo | Comportamiento |
|---|---|
introspection (default) |
Llama a /token/introspect en cada request |
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
Todo lo que necesitas está disponible directamente desde auth_guardian. Aquí un resumen de qué hace cada cosa y cuándo la usarías:
from auth_guardian import (
AuthGuardian, # Lo primero que instancias. Da acceso a get_current_user y require_role.
create_auth_router, # Crea las rutas /login, /oidc/callback y /logout para registrar en tu app.
extract_client_roles, # Función de utilidad: extrae los roles de un cliente a partir del token decodificado.
AuthConfig, # Si necesitas personalizar la configuración más allá de las variables de entorno.
AuthTokenValidator, # Validador de tokens. Úsalo si quieres extender o reemplazar la lógica de validación.
AuthOIDCClient, # Cliente que habla con Keycloak. Útil si necesitas hacer llamadas OIDC directamente.
KeycloakAuthError, # Excepción: el usuario no está autenticado o su sesión no es válida.
TokenValidationError, # Excepción: el token existe pero no pasa la validación.
KeycloakAPIError, # Excepción: no se pudo comunicar con Keycloak (timeout, caída, etc.).
)
Para el uso habitual solo necesitas AuthGuardian y create_auth_router. El resto está disponible si quieres extender el comportamiento o manejar errores de forma personalizada.
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.19.tar.gz.
File metadata
- Download URL: auth_guardian-0.1.19.tar.gz
- Upload date:
- Size: 25.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3ef1fb395392eed31f7eb11d7d0a6f6af9bd4e926429ec38ae0144b0935a06a2
|
|
| MD5 |
1ae8c569607a03dacfde2424b486636b
|
|
| BLAKE2b-256 |
cdede1ce6aba72f00d86353b7cd6bd764564f27b960d825a15b9e8f377c44136
|
File details
Details for the file auth_guardian-0.1.19-py3-none-any.whl.
File metadata
- Download URL: auth_guardian-0.1.19-py3-none-any.whl
- Upload date:
- Size: 22.6 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 |
d0d428a24c9b5b0da5abc63ece1589e4604d232567efed5b77c2def0eb6d87fc
|
|
| MD5 |
53d57953cc5f69d60fdcd260d83df365
|
|
| BLAKE2b-256 |
306ca89e243718d81e8188a9e8c6bae324476ca850160e511075f2c904761886
|