Ciclo de Vida del JSON Web Token (Implementación CFIA)
El flujo implementado sigue las mejores prácticas de seguridad, separando la autenticación del intercambio de tokens y la renovación silenciosa.
-
1. Autenticación (con generación de token temporal):
El usuario se autentica en el IdP. El IdP genera un **Token Temporal** (de corta duración) para iniciar el proceso de intercambio de tokens.
-
2. Obtención de Token (Token\_Exchange):
El SP solicita al *endpoint* `Token_Exchange` el **JWT de Acceso** y el **Token de Refresco**, utilizando el Token Temporal. Este es un proceso Server-Server.
-
3. Renovación de Token:
Antes de que el JWT de Acceso expire (3600s/1 hora), el SP usa el Token de Refresco (86400s/24 horas) para solicitar un nuevo JWT de Acceso y un nuevo Token de Refresco. Esto se hace de forma silenciosa, implementando la **rotación de tokens** para mayor seguridad.
-
4. Cierre de Sesión (JWT\_Logout):
El SP envía una petición al *endpoint* `JWT_Logout` para revocar el Token de Refresco almacenado en `Tc_JWT` y anular la sesión JWT.
Configuración de Proveedor de Identidad (IdP) y Servicios (SP)
Detalles de configuración vitales para la seguridad y el ciclo de vida de los tokens, mapeados a estándares OIDC/OAuth 2.0.
Configuración del Identity Provider (IdP)
El nodo identityProvider define la autoridad central que autentica a los usuarios y emite los tokens.
| Campo de Configuración |
Valor de Ejemplo |
Explicación Técnica (Estándar JWT/OIDC) |
| issuer |
http://localhost:61994 |
Claim JWT: iss (Issuer). URL única que identifica al IdP.
|
| pfxPath / pfxPassword |
~/App_Data/idp-CFIA.pfx / Cf!@IdP |
Ruta y contraseña del archivo PFX que contiene el **certificado** y la **clave privada** del IdP. La clave privada es esencial para firmar los JWT con RS256, garantizando autenticidad.
|
| crtPath |
~/App_Data/idp-CFIA.crt |
Ruta al certificado (clave pública). Esta clave pública se expone para que los SPs verifiquen la firma del JWT.
|
| metadata |
/JWT/OpenId_Metadata.aspx |
Endpoint de Descubrimiento OIDC. URL para que los SPs obtengan automáticamente todos los demás endpoints y configuraciones necesarias del IdP.
|
| tokenLifetime |
3600 (1 hora) |
Tiempo de vida del AccessToken (JWT) en segundos. Se utiliza para el claim exp.
|
| refreshExpiry |
86400 (24 horas) |
Tiempo de vida del RefreshToken. Permite renovar el AccessToken sin reautenticación.
|
Configuración de Clientes SP (Service Providers)
Lista de aplicaciones externas autorizadas para solicitar y usar tokens.
| Campo de Cliente |
Valor de Ejemplo |
Explicación Técnica (Estándar OIDC/OAuth 2.0) |
| clientId |
sp1 |
Parámetro OAuth: client_id. Identificador público único del SP.
|
| redirectUri |
http://localhost:61994/JWT/JWT_SP.aspx |
URL a la que el IdP redirige al usuario con el Código de Autorización. Debe estar pre-registrada por seguridad.
|
| audience |
https://mi-sp-app.com |
Claim JWT: aud (Audience). Identifica al destinatario del JWT (el propio SP).
|
| client_secret |
SP1-asa56446 |
Secreto confidencial usado por el SP para autenticarse en el endpoint de intercambio de tokens (`Token_Exchange`).
🚨 **Nota de Seguridad:** Debe ser manejado como un secreto de alto riesgo, solo en el lado del servidor del SP.
|
Descripción Técnica de Clases Clave (VB.NET)
Las tres librerías críticas implementan la configuración, la criptografía y la persistencia de tokens de refresco, siguiendo el modelo de seguridad.
Clase JwtConfigManager (Configuración y Certificados)
| Método/Propiedad |
Explicación Técnica |
Uso en la Federación |
| GetSigningCert() |
Carga el certificado X509Certificate2 que contiene la clave privada desde la ruta PFX. |
Crítico: Proporciona la clave para que el JwtManager firme los tokens (garantía de autenticidad). |
| GetPublicCert() |
Carga el certificado de clave pública desde la ruta CRT. |
Usado para exponer la clave pública (típicamente en OpenId_Metadata) para que los SPs verifiquen la firma. |
| GetClient(id As String) |
Recupera la configuración de un Cliente/SP a partir de su clientId (ej., redirectUri, client_secret, audience). |
Permite al IdP validar si el SP que solicita un token está registrado y cuáles son sus parámetros de seguridad. |
Clase JwtManager (Emisión y Criptografía JWT)
| Método/Propiedad |
Explicación Técnica |
Estándar JWT/OIDC |
| BuildJwt(...) |
Construye el JWT (Token de Acceso). Define claims (iss, aud), calcula el tiempo de vida (exp), y firma el token con SecurityAlgorithms.RsaSha256. |
**Emisión de JWT/ID Token.** El uso de RS256 garantiza la autenticidad. |
| UseRefreshToken(...) |
Implementa el flujo de renovación de tokens: verifica el token antiguo, obtiene la identidad, genera un nuevo JWT y un nuevo Refresh Token, y llama a RefreshStore.Rotate para eliminar el antiguo. |
**Flujo de Renovación (Token Refresh).** Implementa la rotación de Refresh Tokens, una práctica de seguridad clave para mitigar el robo de tokens. |
| GetToken() y GetTkey() |
Generan cadenas aleatorias de bytes criptográficamente seguras. |
Se utilizan para generar los Refresh Tokens opacos (no JWT) de alta entropía. |
Clase RefreshStore (Almacén de Tokens de Larga Duración)
Gestiona los tokens de larga duración (`RefreshToken`), que son opacos y se almacenan en la base de datos a través de esta clase de persistencia.
| Método/Propiedad |
Explicación Técnica |
Uso en la Federación |
| StoreRefresh(...) |
Almacena una nueva entrada con el Token opaco, el Subject y la expiración (DateTime.UtcNow.AddSeconds(expirySeconds)) en Tc_JWT. |
Asegura la persistencia del token opaco hasta su uso o expiración. |
| IsValid(...) |
Verifica la existencia del token, compara que el ClientId suministrado coincida, y comprueba la expiración, eliminando el token si ha caducado. |
Garantía de Autorización: Asegura que solo el cliente autorizado puede renovar el token y que los tokens expirados se purgan. |
| Rotate(...) |
Elimina el oldToken del almacén. |
Implementa el mecanismo de **un solo uso** para el `RefreshToken`, aumentando la seguridad contra ataques de repetición. |
Adaptaciones Arquitectónicas (SSO-CFIA) y Estándar JWT
A continuación, se detalla la estructura de la arquitectura implementada en SSO-CFIA, complementada por los componentes y flujos del estándar JWT/OIDC.
Nuevos Endpoints (Rutas de Servicio)
- **`/JWT/Token_Exchange`:** URL para intercambiar el token temporal por el Access Token y Refresh Token. (Corresponde al `/token` estándar de OIDC).
- **`/JWT/OpenId_Metadata.aspx`:** Devuelve el documento JSON con los metadatos del IdP (URL de *issuer*, Endpoints, *signing keys*). (Corresponde a `/.well-known/openid-configuration`).
- **`/JWT/JWT_Logout`:** Procesa la revocación del Token de Refresco y cierra la sesión.
- **`/JWT/JWT_SP`:** Página de simulación del SP para pruebas de flujo completo.
Cambios en Persistencia (SQL: 75 LoC)
- **`Tb_JWT`:** Ajuste en la tabla para indicar qué sistemas SP requieren respuesta JWT.
- **`Tc_JWT`:** Nueva tabla para almacenar el valor del **Token de Refresco** (hash y vigencia), esencial para la renovación y cierre de sesión seguro.
I. Componentes Centrales y Roles (Estándar OIDC)
| Componente | Rol y Explicación | Datos Técnicos Clave |
| Proveedor de Identidad (IdP) | Autentica al usuario y emite el JWT (Token de Acceso). Mantiene la clave privada para la firma. | URL de Emisión (iss): La base URL del IdP. |
| Proveedor de Servicio (SP) | Aplicación que consume el JWT. Verifica la firma y autoriza el acceso a recursos. | URL de Audiencia (aud): El identificador del SP. |
| JSON Web Token (JWT) | El Token de Acceso. Formato seguro para transmitir información (Header.Payload.Signature). | Algoritmo de Firma: RS256 (RSA con SHA-256). |
| JSON Web Key Set (JWKS) | Conjunto de claves públicas que el IdP expone para que el SP pueda verificar la firma del JWT. | Endpoint JWKS: URL pública del IdP, ej., /.well-known/jwks.json. |
II. Flujo de Comunicación y Endpoints Estándar (OIDC/OAuth 2.0)
El flujo implementado se basa en el **Código de Autorización** (Authorization Code Flow):
- SP → IdP: El SP redirige al usuario al IdP.
- IdP → Usuario: El IdP autentica al usuario.
- IdP → SP: El IdP devuelve un Código de Autorización (back-channel).
- SP → IdP: El SP intercambia el Código por el Token de Acceso (JWT) y el Refresh Token, usando el
client_secret.
Endpoints OIDC Estándar (Mapeo a CFIA)
| Endpoint Estándar | Propósito |
/authorize | URL para la redirección inicial y la autenticación del usuario. |
/token | URL para intercambiar el código o el refreshToken por el JWT de acceso. (Mapea a /JWT/Token_Exchange en CFIA). |
/.well-known/jwks.json | Contiene la clave pública (JWKS) del IdP para verificar la firma del JWT. |
/.well-known/openid-configuration | Endpoint de descubrimiento para obtener todas las URLs y configuraciones del IdP. (Mapea a /JWT/OpenId_Metadata.aspx en CFIA). |
III. Seguridad y Verificación de Claims
El SP debe implementar la validación de la firma ($RS256$) y la verificación de los siguientes claims:
| Claim (Campo) | Rol de Seguridad | Requisito de Validación del SP |
iss | CRÍTICO: Identificador del Emisor (IdP). | El SP debe verificar que coincida con el IdP configurado. |
sub | CRÍTICO: Identificador único del usuario. | Se usa para el mapeo de cuentas del usuario en el sistema del SP. |
aud | CRÍTICO: Identificador de la Audiencia (SP). | El SP debe rechazar el token si no está dirigido a él. |
exp | CRÍTICO: Tiempo de Expiración (ej., 3600 segundos). | El token debe ser invalidado inmediatamente después de esta hora. |
Manejo de Sesiones: `refreshToken`
- Naturaleza: Token de larga duración (24 horas), opaco (no es un JWT), y de uso restringido.
- Uso: El SP lo envía al endpoint /token (o /JWT/Token_Exchange) del IdP para renovar el JWT de Acceso.
- Almacenamiento: Debe ser almacenado de forma altamente segura (cifrado en base de datos `Tc_JWT`), nunca expuesto en el navegador.
- Revocación: El IdP (`RefreshStore` y JWT_Logout) debe ofrecer un mecanismo para revocar el refreshToken inmediatamente.
🚨 **Nota de Seguridad General:** El SP debe implementar siempre la verificación de los claims iss, aud y exp, y la firma criptográfica (usando $RS256$) del JWT de Acceso.