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
Per inserire un commento, devi avere un account.
Fai il login e torna a questa pagina, oppure registrati alla nostra community.
Approfondimenti
Utilizzare i primary constructor in C#
Migrare una service connection a workload identity federation in Azure DevOps
Usare le navigation property in QuickGrid di Blazor
Registrare servizi multipli tramite chiavi in ASP.NET Core 8
Supportare lo HierarchyID di Sql Server in Entity Framework 8
Effettuare il binding di date in Blazor
Filtrare i dati di una QuickGrid in Blazor con una drop down list
Effettuare il log delle chiamate a function di GPT in ASP.NET Web API
Utilizzare database e servizi con gli add-on di Container App
Criptare la comunicazione con mTLS in Azure Container Apps
Visualizzare le change sul plan di Terraform tramite le GitHub Actions
Creazione di plugin per Tailwind CSS: espandere le funzionalità del framework dinamicamente