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
Effettuare lo stream della risposta in ASP.NET Core tramite IAsyncEnumerable
Utilizzare l'operatore GroupBy come ultima istruzione di una query LINQ in Entity Framework
Gestire undefined e partial nelle reactive forms di Angular
Effettuare il deploy di immagini solo da container registry approvati in Kubernetes
Implementare il throttling in ASP.NET Core
Eseguire un metodo asincrono dopo il set di una proprietà in Blazor 8
Verificare la provenienza di un commit tramite le GitHub Actions
Visualizzare le change sul plan di Terraform tramite le GitHub Actions
Evitare (o ridurre) il repo-jacking sulle GitHub Actions
Reactive form tipizzati con FormBuilder in Angular
Hosting di componenti WebAssembly in un'applicazione Blazor static
Creare alias per tipi generici e tuple in C#
I più letti di oggi
- Miglioramenti nelle performance di Angular 16
- Ottimizzare le performance delle collection con le classi FrozenSet e FrozenDictionary
- HTML5 con CSS e JavaScript
- Ottimizzazione dei block template in Angular 17
- ecco tutte le novità pubblicate sui nostri siti questa settimana: https://aspit.co/wkly buon week-end!