Become a member!

JOSE/JWT Asimmetrico in DelphiMVCFramework: RS256, ECDSA, EdDSA e OpenSSL Moderno

🌐
Questo articolo è disponibile anche in altre lingue:
🇬🇧 English  •  🇪🇸 Español

JOSE, JWT e gli Standard di Settore

Per chi non mastica crittografia quotidianamente, vale la pena inquadrare il contesto. JOSE (Javascript Object Signing and Encryption) è la famiglia di standard IETF che definisce come firmare e cifrare dati in formato JSON. Include:

  • JWT (RFC 7519) — il formato del token (header, payload, firma)
  • JWS (RFC 7515) — la firma digitale dei token
  • JWA (RFC 7518) — gli algoritmi crittografici supportati
  • JWK (RFC 7517) — la rappresentazione delle chiavi in formato JSON

Fino a oggi, DelphiMVCFramework supportava JWT con gli algoritmi HMAC simmetrici (HS256/384/512) — la scelta più comune e perfettamente adeguata per la maggior parte delle applicazioni. Tuttavia, quando l’architettura cresce verso i microservizi, il modello simmetrico impone un compromesso: o tutti i server conoscono lo stesso segreto (aumentando la superficie di attacco), oppure ogni servizio deve validare i token contattando un unico server di autenticazione centralizzato (creando un collo di bottiglia e un single point of failure). La firma asimmetrica elimina entrambi i problemi.

Firma Asimmetrica JWT in Delphi: il Pezzo Mancante

Con la firma asimmetrica il paradigma cambia: l’auth server firma con una chiave privata che non lascia mai quella macchina, e tutti gli altri servizi verificano con la chiave pubblica, che può essere distribuita liberamente. Questo è lo standard per OpenID Connect, OAuth 2.0, e qualsiasi architettura moderna a microservizi.

DelphiMVCFramework ora implementa la copertura completa degli algoritmi JWA per JWS:

Famiglia Algoritmi Note
HMAC HS256, HS384, HS512 Segreto condiviso (già supportato)
RSA PKCS#1 RS256, RS384, RS512 Compatibilità massima, OIDC
RSA-PSS PS256, PS384, PS512 Più sicuro di RS*, stesse chiavi RSA
ECDSA ES256, ES384, ES512 Chiavi molto più piccole di RSA
EdDSA Ed25519 Il più veloce, chiavi da 32 byte

Sedici algoritmi. Quattro famiglie crittografiche. Tutti accessibili attraverso la stessa interfaccia IJWTSigner, che si integra con il middleware JWT esistente senza cambiare una riga di codice nella logica applicativa.

Questo significa che un’applicazione DelphiMVCFramework può ora interoperare nativamente con identity provider come Auth0, Keycloak, Azure AD e Google Identity, che emettono token RS256 o ES256.

OpenSSL 3.x via TaurusTLS

Una scelta architetturale precisa: i nuovi signer non usano le librerie OpenSSL 1.0.x distribuite con Indy (End of Life dalla fine del 2019). Usano TaurusTLS per accedere a OpenSSL 1.1.1+ e 3.x — algoritmi moderni, patch di sicurezza attive, performance superiori.

Dipendenza Opzionale: Zero Impatto sul Codice Esistente

Chi usa HS256 non deve cambiare nulla. TaurusTLS serve solo se usi algoritmi asimmetrici.

L’interfaccia IJWTSigner è definita nel core del framework senza dipendenze esterne. Le implementazioni RSA/ECDSA/EdDSA vivono in una unit separata (MVCFramework.JWT.RSA) che includi solo quando ne hai bisogno.

Come Passare da HS256 a RS256 in DelphiMVCFramework

// PRIMA: HMAC (segreto condiviso)
Engine.AddMiddleware(UseJWTMiddleware(AuthHandler, ClaimsSetup,
  'my_shared_secret', '/login', [...], 300));

// DOPO: RSA (chiave asimmetrica)
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 in più nella uses, una riga per creare il signer, un parametro diverso nel middleware. Controller, auth handler, claims: tutto identico.

E se un microservizio deve solo verificare token senza firmarli:

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

La chiave privata non esiste nemmeno su quella macchina.

Esempio Completo: Creare e Verificare un Token RS256

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

// --- 1. CREARE UN TOKEN (auth server) ---

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. VERIFICARE IL TOKEN (microservizio, solo chiave pubblica) ---

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;

Tutta la Complessità è nel Middleware

In DelphiMVCFramework non devi scrivere codice come quello sopra per ogni richiesta. Il middleware JWT gestisce automaticamente l’intero ciclo: intercetta le richieste, estrae il token dall’header Authorization: Bearer, lo verifica con il signer configurato, popola Context.LoggedUser con claims e ruoli, e rifiuta le richieste non valide con il codice HTTP appropriato. Il tuo controller riceve la richiesta solo se il token è valido — e a quel punto ha già a disposizione l’utente autenticato e i suoi ruoli, senza una sola riga di codice JWT.

Sicurezza JWT Integrata

Oltre agli algoritmi, l’implementazione include protezioni concrete:

  • Algorithm Confusion Prevention: il token non può dichiarare un algoritmo diverso da quello configurato nel signer — previene il noto attacco dove un token RS256 viene ri-firmato come HS256 usando la chiave pubblica
  • Constant-Time Comparison: la verifica HMAC usa confronto a tempo costante per prevenire timing attacks
  • Sign-Only / Verify-Only: un microservizio che deve solo verificare token può essere configurato con la sola chiave pubblica — la chiave privata non viene mai deployata su quella macchina, eliminando il rischio che venga compromessa

Quality: Nessuna Funzionalità Senza Unit Test

Come ogni funzionalità di DelphiMVCFramework, anche il supporto JOSE/JWS è coperto da una nutrita batteria di unit test. Nessuna funzionalità viene rilasciata senza test automatizzati che ne verifichino il corretto funzionamento su tutte le piattaforme supportate. I test coprono tutti e 16 gli algoritmi su Win32 e Win64, inclusi scenari di tamper detection, chiavi errate, algorithm mismatch e backward compatibility con il codice esistente.

E Dopo? JWE e JWK

Il supporto JWS completo è il primo passo. L’architettura basata su IJWTSigner apre la strada a JWE (JSON Web Encryption, RFC 7516) per token cifrati e a JWK (RFC 7517) per la gestione delle chiavi in formato JSON — inclusi gli endpoint JWKS per la distribuzione automatica delle chiavi pubbliche. Stay tuned.

A ITDevCon 2026 Spring Edition

Questa è solo una delle novità che presenterò a ITDevCon 2026 Spring Edition. Vedremo demo live di architetture a microservizi con firma asimmetrica, integrazione con identity provider moderni, e molto altro.

Tutto quello che avete letto in questo articolo è già implementato e funzionante nella versione 3.5.0-silicon attualmente in beta su GitHub. La release stabile è prevista prima di ITDevCon 2026 Spring Edition.

Comments

comments powered by Disqus