Become a member!

JOSE/JWT Asimétrico en DelphiMVCFramework: RS256, ECDSA, EdDSA y OpenSSL Moderno

🌐
Este artículo también está disponible en otros idiomas:
🇬🇧 English  •  🇮🇹 Italiano

JOSE, JWT y los Estándares de la Industria

JOSE (Javascript Object Signing and Encryption) es la familia de estándares IETF que define cómo firmar y cifrar datos en formato JSON. Incluye:

  • JWT (RFC 7519) — el formato del token (header, payload, firma)
  • JWS (RFC 7515) — la firma digital de los tokens
  • JWA (RFC 7518) — los algoritmos criptográficos soportados
  • JWK (RFC 7517) — la representación de claves en formato JSON

Hasta ahora, DelphiMVCFramework soportaba JWT con algoritmos HMAC simétricos (HS256/384/512) — la opción más común, perfectamente adecuada para la mayoría de las aplicaciones. Sin embargo, cuando la arquitectura crece hacia los microservicios, el modelo simétrico impone un compromiso: o todos los servidores conocen el mismo secreto (aumentando la superficie de ataque), o cada servicio debe validar los tokens contactando un único servidor de autenticación centralizado (creando un cuello de botella y un single point of failure). La firma asimétrica elimina ambos problemas.

Firma Asimétrica JWT en Delphi: la Pieza que Faltaba

Con la firma asimétrica, el paradigma cambia: el servidor de autenticación firma con una clave privada que nunca sale de esa máquina, y todos los demás servicios verifican con la clave pública, que puede distribuirse libremente. Este es el estándar para OpenID Connect, OAuth 2.0, y cualquier arquitectura moderna de microservicios.

DelphiMVCFramework ahora implementa la cobertura completa de los algoritmos JWA para JWS:

Familia Algoritmos Notas
HMAC HS256, HS384, HS512 Secreto compartido (ya soportado)
RSA PKCS#1 RS256, RS384, RS512 Máxima compatibilidad, OIDC
RSA-PSS PS256, PS384, PS512 Más seguro que RS*, mismas claves RSA
ECDSA ES256, ES384, ES512 Claves mucho más pequeñas que RSA
EdDSA Ed25519 El más rápido, claves de 32 bytes

Dieciséis algoritmos. Cuatro familias criptográficas. Todos accesibles a través de la misma interfaz IJWTSigner, que se integra con el middleware JWT existente sin cambiar una sola línea en la lógica de la aplicación.

Esto significa que una aplicación DMVCFramework puede ahora interoperar nativamente con proveedores de identidad como Auth0, Keycloak, Azure AD y Google Identity, que emiten tokens RS256 o ES256.

OpenSSL 3.x vía TaurusTLS

Una decisión arquitectónica deliberada: los nuevos signers no usan las librerías OpenSSL 1.0.x distribuidas con Indy (End of Life desde finales de 2019). Usan TaurusTLS para acceder a OpenSSL 1.1.1+ y 3.x — algoritmos modernos, parches de seguridad activos, rendimiento superior.

Dependencia Opcional: Cero Impacto en el Código Existente

Si usas HS256, no necesitas cambiar nada. TaurusTLS se requiere solo cuando usas algoritmos asimétricos.

La interfaz IJWTSigner está definida en el core del framework sin dependencias externas. Las implementaciones RSA/ECDSA/EdDSA viven en una unit separada (MVCFramework.JWT.RSA) que incluyes solo cuando la necesitas.

Cómo Pasar de HS256 a RS256 en DelphiMVCFramework

// ANTES: HMAC (secreto compartido)
Engine.AddMiddleware(UseJWTMiddleware(AuthHandler, ClaimsSetup,
  'my_shared_secret', '/login', [...], 300));

// DESPUÉS: RSA (par de claves asimétricas)
uses MVCFramework.JWT.RSA;

var lSigner := TRSAJWTSigner.CreateFromFiles(JWT_RS256,
  'keys/private.pem', 'keys/public.pem');

Engine.AddMiddleware(UseJWTMiddleware(AuthHandler, ClaimsSetup,
  lSigner, '/login', [...], 300));

Una unit más en la cláusula uses, una línea para crear el signer, un parámetro diferente en el middleware. Controladores, auth handler, claims: todo idéntico.

Y si un microservicio solo necesita verificar tokens sin firmarlos:

var lSigner := TRSAJWTSigner.CreateVerifyOnly(JWT_RS256,
  TFile.ReadAllText('public.pem'));

La clave privada ni siquiera existe en esa máquina.

Ejemplo Completo: Crear y Verificar un Token RS256

uses
  MVCFramework.JWT,
  MVCFramework.JWT.RSA;  // requiere TaurusTLS + OpenSSL 1.1.1+

// --- 1. CREAR UN TOKEN (servidor de autenticación) ---

var lSigner := TRSAJWTSigner.CreateFromFiles(
  JWT_RS256, 'keys/private.pem', 'keys/public.pem');

var lJWT := TJWT.Create(lSigner);
try
  lJWT.Claims.Issuer := 'my-auth-server';
  lJWT.Claims.Subject := 'user42';
  lJWT.Claims.ExpirationTime := Now + OneHour;
  lJWT.Claims.IssuedAt := Now;
  lJWT.CustomClaims['role'] := 'admin';

  var lToken := lJWT.GetToken;
  // eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOi...
finally
  lJWT.Free;
end;

// --- 2. VERIFICAR EL TOKEN (microservicio, solo clave pública) ---

var lVerifier := TRSAJWTSigner.CreateVerifyOnly(
  JWT_RS256, TFile.ReadAllText('keys/public.pem'));

var lVerifyJWT := TJWT.Create(lVerifier);
try
  var lError: string;
  if lVerifyJWT.LoadToken(lToken, lError) then
  begin
    WriteLn('Issuer: ', lVerifyJWT.Claims.Issuer);       // my-auth-server
    WriteLn('Subject: ', lVerifyJWT.Claims.Subject);      // user42
    WriteLn('Role: ', lVerifyJWT.CustomClaims['role']);    // admin
  end;
finally
  lVerifyJWT.Free;
end;

Toda la Complejidad Está en el Middleware

En DelphiMVCFramework no necesitas escribir código como el anterior para cada petición. El middleware JWT gestiona automáticamente el ciclo completo: intercepta las peticiones, extrae el token del header Authorization: Bearer, lo verifica con el signer configurado, rellena Context.LoggedUser con claims y roles, y rechaza las peticiones no válidas con el código HTTP apropiado. Tu controller recibe la petición solo si el token es válido — y en ese punto el usuario autenticado y sus roles ya están disponibles, sin una sola línea de código JWT.

Seguridad JWT Integrada

Más allá de los algoritmos, la implementación incluye protecciones concretas:

  • Algorithm Confusion Prevention: el token no puede declarar un algoritmo diferente al configurado en el signer — previene el conocido ataque donde un token RS256 se re-firma como HS256 usando la clave pública
  • Constant-Time Comparison: la verificación HMAC usa comparación a tiempo constante para prevenir timing attacks
  • Sign-Only / Verify-Only: un microservicio que solo necesita verificar tokens puede configurarse con la sola clave pública — la clave privada nunca se despliega en esa máquina, eliminando el riesgo de que sea comprometida

Calidad: Ninguna Funcionalidad se Publica sin Unit Tests

Como cada funcionalidad de DelphiMVCFramework, el soporte JOSE/JWS está respaldado por una amplia batería de tests automatizados. Ninguna funcionalidad se publica jamás sin tests que verifiquen su correcto funcionamiento en todas las plataformas soportadas. Los tests cubren los 16 algoritmos en Win32 y Win64, incluyendo detección de manipulación, claves incorrectas, algorithm mismatch y backward compatibility con el código existente.

¿Y Después? JWE y JWK

El soporte completo de JWS es el primer paso. La arquitectura basada en IJWTSigner abre el camino hacia JWE (JSON Web Encryption, RFC 7516) para tokens cifrados y JWK (RFC 7517) para la gestión de claves en formato JSON — incluyendo endpoints JWKS para la distribución automática de claves públicas. Stay tuned.

En ITDevCon 2026 Spring Edition

Esta es solo una de las novedades que presentaré en ITDevCon 2026 Spring Edition. Veremos demos en vivo de arquitecturas de microservicios con firma asimétrica, integración con proveedores de identidad modernos, y mucho más.

Todo lo descrito en este artículo ya está implementado y funcionando en la versión 3.5.0-silicon, actualmente en beta en GitHub. La release estable está prevista antes de ITDevCon 2026 Spring Edition.

Comments

comments powered by Disqus