Come implementare l'autenticazione con JWT in un'applicazione Flask

L'autenticazione è un componente cruciale per qualsiasi applicazione web moderna. Quando si sviluppa un'API RESTful, una delle tecniche più popolari ed efficaci per gestire l'autenticazione degli utenti è l'utilizzo di JSON Web Tokens (JWT). Questo approccio non solo semplifica la gestione delle sessioni, ma consente anche di costruire applicazioni scalabili e sicure, in cui non è necessario mantenere lo stato lato server. In questo articolo, esploreremo come implementare un sistema di autenticazione basato su JWT in un'applicazione web realizzata con Flask.
Un JSON Web Token (JWT) è un metodo di rappresentazione sicura e compatta delle informazioni, utile per l'autenticazione tra il client e il server. La struttura di un JWT è composta da tre sezioni: l'intestazione (header), il payload e la firma. L'intestazione contiene informazioni sul tipo di token e sull'algoritmo di firma utilizzato. Il payload contiene i dati effettivi che vogliamo trasmettere, come l'ID dell'utente. La firma serve per garantire che il token non venga alterato durante il suo percorso. La grande vantaggio di JWT risiede nel fatto che sono auto-contenuti, il che significa che tutte le informazioni necessarie per l'autenticazione sono incluse nel token stesso, evitando la necessità di memorizzare sessioni sul server.
Creazione dell'applicazione Flask
Per cominciare, installiamo Flask e altre librerie necessarie per lavorare con JWT, come pyjwt e flask_sqlalchemy. La libreria flask_sqlalchemy ci permette di gestire facilmente il database, mentre pyjwt sarà utilizzata per generare e validare i JWT.
Per installare le librerie, esegui il comando:
Iniziamo a configurare la nostra applicazione Flask. Creiamo un file app.py e definiremo una semplice applicazione Flask con un modello di database per gli utenti. Ecco come possiamo fare:
Abbiamo configurato un'applicazione di base in Flask con un database SQLite. Il modello User è stato definito per memorizzare gli utenti con un campo username e password. La chiave segreta SECRET_KEY è utilizzata per firmare il token JWT, ed è importante cambiarla con una chiave unica e sicura per la tua applicazione.
Registrazione di un nuovo utente
La registrazione di un nuovo utente è il primo passo verso l'autenticazione. Creiamo una route /register che accetta una richiesta POST per registrare un utente. Il nome utente e la password vengono presi dal corpo della richiesta, quindi verifichiamo se l'utente esiste già nel database. Se l'utente non esiste, lo creiamo e memorizziamo nel database. Ecco come:
In questo codice, la funzione register esegue le seguenti operazioni:
- Estrae i dati dal corpo della richiesta.
- Verifica se il nome utente e la password sono forniti.
- Controlla se l'utente esiste già nel database.
- Se l'utente non esiste, viene creato e salvato nel database.
Autenticazione con JWT
Ora che abbiamo un sistema di registrazione, possiamo implementare il login degli utenti. La route /login restituirà un JWT quando le credenziali dell'utente sono corrette. Questo è fondamentale perché il JWT rappresenta l'autenticazione dell'utente e sarà utilizzato per accedere a endpoint protetti. Quando l'utente inserisce il nome utente e la password, Flask verifica se queste corrispondono ai dati nel database. Se sono corretti, viene generato un JWT che contiene l'ID dell'utente e la scadenza del token. Ecco come implementare il login:
In questa funzione:
- Controlliamo se l'utente esiste e se la password è corretta.
- Se le credenziali sono valide, generiamo un token JWT.
- Il token contiene l'ID dell'utente e una scadenza di un'ora. La scadenza è importante per limitare la durata di validità del token.
Proteggere gli endpoint con JWT
Una delle caratteristiche principali di JWT è che possiamo usarlo per proteggere gli endpoint della nostra applicazione. Creiamo un decoratore token_required, che verificherà che ogni richiesta a un endpoint protetto contenga un token valido. Se il token non è presente o è invalido, verrà restituito un errore. Ecco come:
Abbiamo definito il decoratore token_required che estrae il token dall'intestazione Authorization della richiesta, lo decodifica e verifica la sua validità. Se il token è valido, prosegue con l'esecuzione della funzione, passando l'utente corrente come parametro. Se il token è mancante o invalido, viene restituito un errore.
Ora, possiamo applicare questo decoratore a qualsiasi endpoint che desideriamo proteggere, come ad esempio una route che restituisce i dettagli dell'utente:
In questa route, l'utente dovrà fornire un token valido per accedere alle informazioni del proprio profilo.
Conclusione
Abbiamo visto come implementare un sistema di autenticazione sicuro con JWT in un'applicazione Flask. L'approccio basato su JWT è particolarmente utile per le applicazioni moderne che richiedono una gestione dell'autenticazione senza sessione, poiché consente di gestire l'accesso in modo stateless, senza la necessità di memorizzare sessioni sul server. Inoltre, il sistema di scadenza del token garantisce una maggiore sicurezza. Con la protezione degli endpoint tramite il decoratore token_required, l'applicazione è ora pronta per gestire in modo sicuro gli utenti autenticati.