Invalidare un token JWT prima della scadenza con ASP.NET Core Identity

di Moreno Gentili, in ASP.NET Core,

In un precedente script (https://www.aspitalia.com/script/1288/Autenticazione-JWT-Token-ASP.NET-Core-Web-API.aspx) abbiamo visto come implementare l'autenticazione con Token JWT in un'applicazione ASP.NET Core Web API. Questo genere di autenticazione è utile soprattutto quando la Web API viene consumata da un'applicazione mobile, dato che è molto più sicuro memorizzare un token che ha durata e ambito limitati piuttosto che lo username e la password dell'utente.

Scegliere la data di scadenza del token


Un token viene sempre emesso con una data di scadenza e, se questa scadenza è a breve termine, l'utente dovrà reinserire username e password dopo ogni breve periodo di inattività. Questo "fastidio" che causiamo agli utenti è giustificato dal fatto che un eventuale furto o smarrimento del dispositivo potrebbe avere ripercussioni ben più gravi. Infatti, dato che i dispositivi mobile sono ormai sempre più integrati con i processi produttivi aziendali, potrebbero consentire a un malintenzionato di accedere a segreti aziendali se non adoperassimo criteri di sicurezza stringenti come questo.

Ha senso, dunque, emettere token JWT con scadenza molto breve (ad esempio 20 minuti) ed emetterne di nuovi con scadenza rinnovata fintanto che l'utente continua ad usare l'applicazione (una tecnica chiamata anche "sliding expiration").

D'altra parte, è anche vero che non tutte le applicazioni hanno la necessità di implementare criteri così severi: infatti, se non vengono trattati dati sensibili, potremmo anche decidere di emettere token con scadenze più lunghe (ad esempio di 1 mese).

Se lo facciamo, dobbiamo considerare che per l'utente non è mai piacevole sapere che i suoi dati, fossero anche anche una semplice lista della spesa, sono accessibili a sconosciuti in caso di furto del dispositivo. Con ASP.NET Core Identity però possiamo fare in modo che l'utente stesso possa invalidare il token ben prima della sua scadenza e per far questo gli basterà cambiare la password dal sito web o da un'altra installazione dell'app mobile. Vediamo quali sono i passi per implementare questo utile accorgimento.

Invalidare prematuramente un token grazie al Security Stamp


Quando un token JWT viene emesso, contiene un claim valorizzato con il Security Stamp, ovvero un codice opaco e generato casualmente che è memorizzato nel database insieme agli altri dati dell'utente.


Quando l'utente cambia la password, ASP.NET Core Identity rigenera il Security Stamp. Quindi non ci resta che coinvolgere anche il Security Stamp nel processo di validazione del token JWT: solo se corrisponde a quello memorizzato nel database, allora il token sarà reputato valido.

Rispetto all'applicazione fornita a corredo del precedente script (http://aspit.co/brl), dovremo recarci nel metodo Configure della classe Startup e modificare in questo modo:

services.AddAuthentication(options =>
{
  options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{
  //Impostiamo i TokenValidationParameters come da precedente script
  options.TokenValidationParameters = new TokenValidationParameters
  {
    /* omissis: il codice resta inviariato rispetto al precedente script */
  };
  
  //Poi, aggiungiamo la validazione del Security Stamp
  options.Events = new JwtBearerEvents
  {
    OnTokenValidated = async (validationContext) => 
    {
      //Otteniamo un riferimento al SignInManager
      var signInManager = validationContext.HttpContext
        .RequestServices.GetRequiredService<SignInManager<ApplicationUser>>();

      //Validiamo la principal corrente, in cui si trovano i claim del Security Stamp e dello username
      var user = await signInManager.ValidateSecurityStampAsync(validationContext.Principal);
    
      //Se è stato trovato un utente corrispondente, allora significa che il Security Stamp corrisponde
      if (user != null)
      {
        validationContext.Success();
        return;
      }

      //Altrimenti vuol dire che il Security Stamp è cambiato.
      //La validazione del token deve considerarsi fallita.
      validationContext.Fail("Security Stamp not valid");
    }
  };
});

Questa tecnica è anche chiamata "Sign-out remoto" e può essere attuata anche per l'autenticazione basata sui cookie.

Conclusione


Grazie ad ASP.NET Core Identity e al Security Stamp mettiamo in condizione l'utente di invalidare i token JWT già emessi, per una migliore protezione dei suoi dati, anche in presenza di scadenze lunghe. Questa tecnica, però, implica che il Security Stamp venga confrontato con quello presente nel database e si sa che ogni query al database ha l'effetto collaterale di aumentare il tempo di esecuzione della richiesta. Eventualmente, per mitigare un po' questo problema, potremmo sfruttare il servizio di caching di ASP.NET Core per controllare il Security Stamp solo una volta ogni 5 o 20 minuti.

Commenti

Visualizza/aggiungi commenti

| Condividi su: Twitter, Facebook, LinkedIn

Per inserire un commento, devi avere un account.

Fai il login e torna a questa pagina, oppure registrati alla nostra community.

Approfondimenti

I più letti di oggi