Flujo de verificación y autenticación
El Credential IDP de ISBE es un Identity Provider (IDP) federado que permite a cualquier sistema compatible con OpenID Connect delegar la fase de autenticación a un proceso basado en presentación de credenciales verificables. El IDP actúa como intermediario entre Keycloak y el servicio de verificación de ISBE.
Qué hace el Credential IDP
En lugar de pedir usuario y contraseña, el IDP muestra al usuario un código QR que este escanea con su wallet digital. El wallet envía la credencial verificable (VC) al servicio de verificación de ISBE, que la valida criptográficamente y notifica al IDP. Si la validación es correcta, el IDP genera un token OIDC y lo entrega a Keycloak, que finaliza el proceso de autenticación y redirige al usuario al portal ISBE con la sesión iniciada.
Arquitectura
Usuario (navegador)
│ 1. Accede al portal ISBE
▼
Portal ISBE ──► Keycloak (delega autenticación)
│ 2. Redirige al IDP de credenciales
▼
Credential IDP ──► muestra QR al usuario
│ │
│ polling │ 3. Usuario escanea QR
│ ▼
│ Wallet digital del usuario
│ │
│ │ 4. Presenta VC
│ ▼
│ Servicio de verificación
│ │ 5. Valida VC criptográficamente
│ │ (verifica firma contra DID del emisor)
│ │ 6. Notifica al IDP (POST /idp/api/auth/requests)
◄──────────────┘
│ 7. IDP genera tokens OIDC
▼
Keycloak (recibe token)
│ 8. Finaliza autenticación
▼
Portal ISBE (sesión iniciada)
Flujo paso a paso
1. El usuario accede al portal ISBE
El usuario navega al portal ISBE y hace clic en "Iniciar sesión". El portal redirige a Keycloak para gestionar la autenticación.
2. Keycloak redirige al Credential IDP
El usuario elige autenticarse mediante credencial verificable. Keycloak redirige al endpoint de autorización del IDP (/accounts/authorize) con los parámetros OAuth2 estándar (incluido el scope que representa el tipo de credencial que debe presentar el usuario).
3. El IDP muestra el QR
El IDP genera una sesión de verificación y renderiza una página HTML con:
- Un código QR que el usuario debe escanear con su wallet.
- Un campo de texto informativo con el
scope(tipo de credencial) que se solicita al usuario. - Un mecanismo de polling (el navegador consulta periódicamente
GET /idp/api/auth/requestscon el código de sesión para saber si la verificación ya fue completada).
4. El usuario escanea el QR con su wallet
El wallet lee la URL de oferta de credencial codificada en el QR. Esta URL sigue el protocolo OID4VP (OpenID for Verifiable Presentations).
5. El wallet presenta la VC
El wallet selecciona la VC adecuada según el tipo solicitado (OID_CREDENTIAL, por defecto IsbePortalLearCredential) y la envía firmada. El servicio de verificación comprueba:
- Que la firma del JWT de la VC es válida para la clave del
assertionMethoddel emisor según el DID Document. - Que el emisor está registrado en el TIR con la acreditación correspondiente al tipo de VC.
- Que la VC no ha expirado y no ha sido revocada.
6. La verificación se completa
Una vez verificada la credencial, el IDP recibe la notificación con los claims:
El IDP guarda los claims en la caché con clave session_code y marca la sesión como SUCCESS.
7. El navegador detecta el éxito (polling)
El navegador del usuario, que estaba haciendo polling a GET /idp/api/auth/requests?session=<código>, recibe la respuesta {"status": "SUCCESS"} y redirige automáticamente al flujo OAuth2.
8. El IDP aplica los mappers y genera los tokens OIDC
El IDP transforma los claims de la VC presentada en atributos del token OIDC según la configuración de mappers del scope activo. Por ejemplo, para el scope openid-vp-lear:
username = credentialSubject.mandate.mandatee.email
given_name = credentialSubject.mandate.mandatee.firstName
name = concat(firstName, ' ', lastName)
family_name = credentialSubject.mandate.mandatee.lastName
preferred_username= credentialSubject.mandate.mandatee.email
organization = credentialSubject.mandate.mandator.organization
organization_identifier = credentialSubject.mandate.mandator.organizationIdentifier
user_identifier = credentialSubject.mandate.mandatee.employeeId
email = credentialSubject.mandate.mandatee.email
power = str(credentialSubject.mandate.power)
El IDP genera el id_token, access_token y refresh_token firmados con su clave RSA privada (IDP_OIDC_PRIVATE_KEY).
El IDP firma los tokens OIDC únicamente con claves RSA, por una limitación de la librería AllAuth. No es posible usar claves EC (P-256, secp256k1) para firmar los tokens del IDP en la versión actual.
9. Keycloak finaliza la autenticación
Keycloak recibe el id_token del IDP, mapea los atributos a sus propios claims y devuelve al usuario al portal ISBE con la sesión iniciada.
Scopes y mappers
El Credential IDP está diseñado para ser configurable por entorno. El administrador del IDP puede crear múltiples scopes, cada uno representando un tipo de presentación distinto.
Un scope tiene:
- Scope: Identificador del tipo de presentación que se solicita al usuario.
- Name: Nombre descriptivo interno.
- Consent Text: Texto que se muestra al usuario cuando se le solicita presentar la credencial.
- Mappers: Reglas de transformación de claims.
Los mappers soportan tres operaciones:
| Operación | Sintaxis | Ejemplo |
|---|---|---|
| Copia directa de atributo | clave = ruta.al.campo | email = mandatee.email |
| Concatenación | clave = concat(v1, sep, v2) | name = concat(mandatee.firstName, ' ', mandatee.lastName) |
| Serialización JSON | clave = str(campo) | power = str(power) |
El IDP actualmente solo procesa correctamente presentaciones de una única credencial. No presentar más de una credencial por sesión de autenticación.
Clientes OIDC registrados en el IDP
Cada sistema que quiera usar el IDP de credenciales (actualmente Keycloak, que actúa como broker) debe estar registrado como cliente OIDC en el panel de administración del IDP. La configuración mínima de un cliente incluye:
Client ID: Identificador del cliente.Scopes: Lista de scopes permitidos (p. ej.openid,profile,email,openid-vp-lear).Redirect URIs: La URL de retorno de Keycloak (https://<keycloak-domain>/broker/<alias-idp>/endpoint).CORS Allowed Origins: Dominio de Keycloak.
Endpoints OIDC del IDP
El IDP expone los endpoints estándar de OpenID Connect:
| Endpoint | Descripción |
|---|---|
GET /.well-known/openid-configuration | Discovery document OIDC con la lista de endpoints y scopes soportados. |
GET /accounts/authorize | Endpoint de autorización OAuth2. Redirige al usuario a la pantalla de QR. |
POST /accounts/token | Intercambio de código de autorización por access_token, id_token y refresh_token. |
GET /accounts/userinfo | Devuelve los claims del usuario autenticado según los scopes solicitados. |
GET /idp/api/auth/requests | Polling del estado de la sesión de verificación (PENDING / SUCCESS / FAILED). |