Este proyecto es un ejemplo completo y didáctico de cómo implementar autenticación OpenID Connect (OIDC) usando:
- Keycloak como Proveedor de Identidad (IdP)
- Python + Flask como aplicación cliente (Relying Party)
- Authorization Code Flow + PKCE
- Logout local y logout completo (Front-channel logout)
Está pensado para talleres formativos, laboratorios o pruebas de concepto.
┌──────────┐ ┌──────────────┐ ┌──────────────┐
│ Usuario │───────▶│ Flask Server │───────▶│ Keycloak │
│ Browser │◀───────│ (RP) │◀───────│ (OIDC IdP) │
└──────────┘ └──────────────┘ └──────────────┘
Componentes:
- Keycloak: gestiona identidad, login y emisión de tokens
- Flask app: aplicación protegida por OIDC
- OIDCClient: librería Python que encapsula la lógica OIDC
.
├── app/
│ └── server.py # Aplicación Flask (Relying Party)
├── client.py # Cliente OIDC (Authlib)
├── docker-compose.yml # Keycloak
├── .env # Variables de entorno (NO commitear)
└── README.md
docker compose up -dAcceso:
- URL: http://localhost:8080
- Usuario: admin
- Password: admin
- Nombre:
master(o uno nuevo si lo prefieres)
- Client ID:
python-app - Client type: OpenID Connect
- Client authentication: Enabled
- Authorization Code Flow: Enabled
- PKCE: Required
-
Redirect URI:
http://localhost:5002/callback -
Post logout redirect URI:
http://localhost:5002/ -
Web origins:
http://localhost:5002
Desde la pestaña Credentials:
CLIENT_IDCLIENT_SECRET
- Username:
demo - Password:
demo123 - Password temporal: ❌
Crear fichero .env:
ISSUER=http://localhost:8080/realms/master
CLIENT_ID=python-app
CLIENT_SECRET=PEGA_AQUI_EL_SECRETpython3 -m venv venv
source venv/bin/activate
pip install flask authlib requests python-dotenvpython app/server.pyAcceder a:
http://localhost:5002
- Usuario accede a
/login - Redirección a Keycloak
- Login del usuario
- Keycloak devuelve
authorization_code - Flask intercambia el código por tokens
- Se valida el ID Token (JWT)
- Se crea sesión local
-
ID Token
- Identidad del usuario
- Firmado por Keycloak
- Validado con JWKS
-
Access Token
- Usado para
/userinfo
- Usado para
Endpoint:
/logout
- Limpia la sesión Flask
- ❌ No cierra sesión en Keycloak
Endpoint:
/logout_full
Flujo:
- Se obtiene
id_tokende la sesión - Se limpia sesión local
- Redirección al endpoint de logout de Keycloak:
/protocol/openid-connect/logout
Parámetros usados:
id_token_hintclient_idpost_logout_redirect_uri
Esto cierra la sesión del usuario tanto en la app como en Keycloak.
✔ Authorization Code Flow
✔ PKCE
✔ Validación de firma JWT
✔ Validación de aud, exp
✔ Protección CSRF con state
✔ Separación cliente OIDC / aplicación
- Explicar OAuth2 vs OIDC
- Analizar JWTs en vivo
- Mostrar JWKS y validación de firma
- Comparar logout local vs global
- Introducir conceptos enterprise (back-channel logout)