Il pulsante di emergenza: revoca immediata dei token in .NET 10 con Duende IdentityServer
Immagina questo scenario da incubo: il telefono di un cliente bancario viene rubato, l’app mobile è già autenticata, e il ladro ha pieno accesso al suo conto. Il supporto riceve la chiamata disperata. Ogni secondo conta. Quanto tempo ci vuole per revocare quella sessione attiva e mettere al sicuro i fondi?
Se stai usando JWT self-contained standard, la risposta onesta potrebbe essere “fino a un’ora”, a seconda della durata di validità del token. Non è accettabile. Vediamo come i Reference Token ti forniscono un vero pulsante di emergenza per queste situazioni, e come configurarli con Duende IdentityServer in .NET 10.
Il problema dei JWT self-contained
I JWT self-contained sono il cavallo di battaglia dell’autorizzazione moderna. Trasportano tutte le claim di cui un’API ha bisogno direttamente nel token. Nessuna query al database, nessuna chiamata al provider di identità. L’API valida la firma, controlla la scadenza, e il gioco è fatto. È elegante e performante.
Ma questa natura self-contained è un’arma a doppio taglio. Una volta emesso un JWT, il provider di identità non ha più nulla da dire su di esso. Il token è valido fino a quando la claim exp non dice il contrario, tipicamente 5-60 minuti. Se un dispositivo viene rubato, un account compromesso, o una minaccia rilevata, non puoi revocare quel token. Sei costretto ad aspettare che scada.
Per molte applicazioni questo compromesso è accettabile. Per ambienti ad alta sicurezza come banking, sanità o sistemi governativi, è un gap che non puoi permetterti.
Reference Token: premere il pulsante
I Reference Token ribaltano il modello. Invece di incorporare tutte le claim direttamente nel token, IdentityServer memorizza il contenuto del token lato server nel suo persisted grant store e consegna al client un identificatore opaco (un “handle”). Quando un’API riceve questo handle, chiama l’endpoint di introspection di IdentityServer per validare il token e recuperare le claim.
Questo cambia tutto. Poiché i dati del token risiedono sul server, puoi cancellarli in qualsiasi momento. La revoca è immediata. La prossima volta che l’API chiama l’endpoint di introspection, riceve "active": false, e l’accesso viene negato. Niente attese di scadenza, niente token obsoleti in circolazione.
Il compromesso? Ogni chiamata API richiede un round-trip verso l’endpoint di introspection. Per API pubbliche su scala internet, è una preoccupazione. Per servizi interni e ambienti ad alta sicurezza, è un prezzo ragionevole per la capacità di staccare la spina istantaneamente.
Configurare i Reference Token in IdentityServer
Passare a Reference Token per un client richiede una singola riga di configurazione. Quando definisci il client in Duende IdentityServer, imposta la proprietà AccessTokenType:
new Client
{
ClientId = "banking_app",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Code,
// Questa è la riga chiave
AccessTokenType = AccessTokenType.Reference,
AllowOfflineAccess = true,
RedirectUris = { "https://banking.example.com/signin-oidc" },
AllowedScopes = { "openid", "profile", "accounts.read", "transfers.write" }
};
I token emessi per questo client saranno ora handle opachi invece di JWT self-contained.
Configurare l’API per l’introspection
La tua API deve sapere come validare questi token opachi. Invece del (o in aggiunta al) classico JWT validation, configuri l’introspection OAuth 2.0. Prima, definisci un API Resource con un secret:
new ApiResource("banking_api")
{
Scopes = { "accounts.read", "transfers.write" },
ApiSecrets = { new Secret("api_secret".Sha256()) }
};
Poi nel Program.cs della tua API, registra l’handler di introspection:
builder.Services.AddAuthentication("token")
.AddOAuth2Introspection("token", options =>
{
options.Authority = "https://identity.banking.example.com";
options.ClientId = "banking_api";
options.ClientSecret = "api_secret";
});
Se devi supportare sia JWT che Reference Token (magari durante una migrazione), puoi registrare entrambi gli handler e usare il forwarding per instradare i token a quello corretto:
builder.Services.AddAuthentication("token")
.AddJwtBearer("token", options =>
{
options.Authority = "https://identity.banking.example.com";
options.Audience = "banking_api";
options.TokenValidationParameters.ValidTypes = ["at+jwt"];
options.ForwardDefaultSelector = Selector.ForwardReferenceToken("introspection");
})
.AddOAuth2Introspection("introspection", options =>
{
options.Authority = "https://identity.banking.example.com";
options.ClientId = "banking_api";
options.ClientSecret = "api_secret";
});
Revocare un token
Quando quella chiamata disperata arriva, il tuo sistema di supporto (o una pipeline automatica di rilevamento minacce) può revocare il token immediatamente usando l’endpoint di revocation di IdentityServer, che implementa la RFC 7009:
using Duende.IdentityModel.Client;
var client = new HttpClient();
var result = await client.RevokeTokenAsync(new TokenRevocationRequest
{
Address = "https://identity.banking.example.com/connect/revocation",
ClientId = "banking_app",
ClientSecret = "secret",
Token = stolenAccessToken
});
if (result.IsError)
{
logger.LogError("Token revocation failed: {Error}", result.Error);
}
Una volta revocato, il token viene rimosso dal persisted grant store. La prossima richiesta di introspection da qualsiasi API confermerà che il token non è più attivo. L’accesso è tagliato.Non dimenticare: dovresti anche revocare il refresh token dell’utente per impedire al client di ottenere silenziosamente un nuovo access token:
await client.RevokeTokenAsync(new TokenRevocationRequest
{
Address = "https://identity.banking.example.com/connect/revocation",
ClientId = "banking_app",
ClientSecret = "secret",
Token = refreshToken
});
Nota: sia l’introspection che la revocation emettono eventi di audit che puoi usare per implementare log di audit nei settori regolamentati.
Quando usare i Reference Token
I Reference Token non sono un sostituto universale dei JWT. Brillano in scenari specifici:
- La revoca immediata è un requisito imprescindibile (banking, sanità, sistemi compliance-driven)
- Comunicazione service-to-service interna dove il round-trip di introspection è trascurabile
- Operazioni ad alto rischio dove il beneficio di sicurezza supera il costo in performance
Per API pubbliche su larga scala dove la latenza di revoca è accettabile, i JWT self-contained con breve durata rimangono una scelta solida. Puoi anche mixare i due approcci: Reference Token per client sensibili e JWT per quelli a minor rischio, tutto all’interno dello stesso deployment IdentityServer.
Conclusione
Ogni architettura di sicurezza implica compromessi. I JWT self-contained scambiano la revocabilità per la performance. I Reference Token scambiano la performance per il controllo. Per gli ambienti dove “aspetta che scada” non è una risposta accettabile, i Reference Token con Duende IdentityServer ti forniscono un vero pulsante di emergenza.
L’implementazione è semplice: una proprietà sul client, un handler di introspection sull’API, e una chiamata di revocation quando devi staccare la spina. Quando accadono incidenti di sicurezza — e accadranno — sarai felice di averlo configurato.
Fonte originale: The Emergency Stop Button – Implementing Immediate Token Revocation in .NET 10 — Khalid Abuhakmeh, Duende Software (28 aprile 2026)
Learn how to implement an immediate 'emergency stop' button for compromised sessions using Reference Tokens and Duende IdentityServer in .NET 10.
Khalid Abuhakmeh (Duende Software)
AV
in reply to Rivoluzione mobilità urbana🚲 • • •Energia, fonti rinnovabili, approvvigionamento e mobilità reshared this.
Rivoluzione mobilità urbana🚲
in reply to AV • • •@L_Alberto pensa che quel sindaco dice pure che quei ciclisti non portano soldi alle attività locali.
Doppiamente idiota.
@energia
Energia, fonti rinnovabili, approvvigionamento e mobilità reshared this.
Contropedale
in reply to Rivoluzione mobilità urbana🚲 • • •Il Garda ha portato un turismo di massa che arriva prevalentemente in auto.
Quello stesso turismo di massa tedesco e olandese che spesso va sul Garda anche per godersi il territorio in bici.
Interessante anche il come viene raccontata dai media la situazione: "ciclisti che si mettono in pericolo da soli. Impediamo la loro circolazione per tutelarli..."
bresciaoggi.it/territorio-bres…
In bici sulla Gardesana ai 15 all’ora: lunghe code, pericolo e proteste
Luciano Scarpetta (Bresciaoggi.it)Energia, fonti rinnovabili, approvvigionamento e mobilità reshared this.
Rivoluzione mobilità urbana🚲
in reply to Contropedale • • •La narrazione degli #autonarcotizzati è sempre la stessa: le bici sono pericolose, quindi vanno limitate, ma per tutelare chi ci va, che premurosi.
Inoltre il genio aggiunge anche la verità, senza accorgersene:
Traduco: chi va in auto deve potersi distrarre alla guida, senza il rischio di investire nessuno, cosa che turberebbe la sua serenità, probabilmente a causa della possibile ammaccatura sull'auto, o di qualche chiazza di sangue sul cofano.
@L_Alberto @energia
Energia, fonti rinnovabili, approvvigionamento e mobilità reshared this.
anacleto
in reply to Contropedale • • •@yogurt @L_Alberto
Beccatevi il Sindaco del mio paese, Lazise. Sul giornale il virgolettato che riassumo: "sulla gardesana solo le automobili, mentre sulla ciclopedonale affianco, solo bici elettriche. Sul lungolago ci devono andare tutte le altre bici"...coi: bagnanti, pedoni, passeggini, cani al guinzaglio, giocatori di volano, monopattini, skateboard...
P.S: il Sindaco Damiano Bergamini odia le PEC perciò se volete scrivergli comune.lazise.urp@halleypec.it
reshared this
Rivoluzione mobilità urbana🚲, rag. Gustavino Bevilacqua, AV e Energia, fonti rinnovabili, approvvigionamento e mobilità reshared this.
anacleto
in reply to Contropedale • • •@yogurt @L_Alberto
Lo scrissi parecchi anni fa, dopo aver letto la storia di un illustre lacisiense.: Vittorio cavaZocca Mazzanti. Come siamo caduti in basso a Lazise!
Energia, fonti rinnovabili, approvvigionamento e mobilità reshared this.