Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

JWT per autenticazione e protezione delle API

JWT: impariamo ad implementare i JSON Web Tokens per l'autenticazione e per la protezione delle API nei nostri progetti
JWT: impariamo ad implementare i JSON Web Tokens per l'autenticazione e per la protezione delle API nei nostri progetti
Link copiato negli appunti

Nel corso delle lezioni precedenti abbiamo acquisito una solida comprensione dei fondamenti di OAuth 2.0 e dei JSON Web Tokens (JWT). In questa lezione, ci concentreremo sull'implementazione pratica di JWT per l'autenticazione e la protezione delle API. Vedremo come generare, convalidare e utilizzare i JWT in un'architettura basata su API, affrontando anche le migliori pratiche di sicurezza.

Cos'è un JSON Web Token (JWT)?

Come abbiamo visto nella lezione precedente, un JSON Web Token è uno standard aperto (RFC 7519) che permette la trasmissione sicura di informazioni tra le parti come oggetti JSON firmati. I JWT vengono spesso utilizzati per l'autenticazione stateless, eliminando la necessità di mantenere sessioni sul server. Essi sono composti in breve da tre parti:

  • Header: contiene il tipo di token e l'algoritmo di firma utilizzato (es. HS256, RS256).

  • Payload: contiene le informazioni (o "claims") come l'ID utente, il ruolo e la scadenza del token.

  • Signature: viene utilizzata per verificare che il token non sia stato alterato.

Un JWT ha poi il seguente formato:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX2lkIjoxMjMsInJvbGUiOiJhZG1pbiIsImV4cCI6MTY5MDg3NTYwMH0.wzYzx-MEFIXYVQblW9pRFLUpDyl3CcrAvfKkQtIvxQw

Generazione di un JWT

Per generare un JWT, possiamo utilizzare una libreria come jsonwebtoken in Node.js o pyjwt in Python. Supponiamo di avere un backend in Node.js con Express. Possiamo generare un JWT come segue:

const jwt = require('jsonwebtoken');
const secretKey = "supersegreta123";
function generateToken(user) {
    const payload = {
        userId: user.id,
        role: user.role
    };
    return jwt.sign(payload, secretKey, { expiresIn: '1h' });
}
const user = { id: 123, role: 'admin' };
const token = generateToken(user);
console.log("JWT Generato:", token);

Questo JWT conterrà l'ID utente e il ruolo, con una scadenza di un'ora.

Analogamente, in un ambiente PHP possiamo utilizzare la libreria firebase/php-jwt per generare un JWT:

require 'vendor/autoload.php';
use Firebase\JWT\JWT;
$secretKey = "supersegreta123";
function generateToken($user) {
    $payload = [
        "userId" => $user["id"],
        "role" => $user["role"],
        "exp" => time() + 3600 // Scadenza tra un'ora
    ];
    return JWT::encode($payload, $secretKey, 'HS256');
}
$user = ["id" => 123, "role" => "admin"];
$token = generateToken($user);
echo "JWT Generato: " . $token;

Validazione di un JWT

Una volta generato un JWT, dobbiamo verificare la sua validità quando viene utilizzato per accedere a un'API protetta. Supponiamo che l'utente invii il token nell'Authorization Header della richiesta HTTP:

In Node.js:

const express = require('express');
const app = express();
function authenticateToken(req, res, next) {
    const token = req.header('Authorization')?.split(' ')[1];
    if (!token) return res.status(401).json({ message: "Accesso negato" });
    jwt.verify(token, secretKey, (err, user) => {
        if (err) return res.status(403).json({ message: "Token non valido" });
        req.user = user;
        next();
    });
}
app.get('/api/protetta', authenticateToken, (req, res) => {
    res.json({ message: "Accesso consentito", user: req.user });
});
app.listen(3000, () => console.log('Server avviato su porta 3000'));

 authenticateToken verifica se il JWT è valido e, in tal caso, permette l'accesso alla risorsa protetta.

Se utilizziamo PHP, possiamo validare un JWT come segue:

use Firebase\JWT\JWT;
use Firebase\JWT\Key;
$secretKey = "supersegreta123";
function validateToken($token) {
    try {
        $decoded = JWT::decode($token, new Key($secretKey, 'HS256'));
        return $decoded;
    } catch (Exception $e) {
        return null;
    }
}
$token = "inserire_il_token_qui";
$decoded = validateToken($token);
if ($decoded) {
    echo "Accesso consentito: ";
    print_r($decoded);
} else {
    echo "Token non valido.";
}

In breve, questo codice in PHP utilizza la libreria Firebase JWT per verificare la validità di un token. Dopo aver definito una chiave segreta, implementa la funzione validateToken che tenta di decodificare il token utilizzando l'algoritmo HS256. Se la decodifica ha successo, restituisce il payload del token; in caso di errore, cattura l'eccezione e restituisce null. Successivamente, il codice assegna a $token un valore predefinito e lo passa alla funzione di validazione. Se il token è valido, stampa il payload, altrimenti mostra un messaggio di errore.

Tuttavia, il codice presenta alcune criticità, come l'uso di una chiave segreta poco sicura e la mancata gestione dettagliata degli errori, che potrebbero compromettere la sicurezza dell'applicazione.

Utilizzo di JWT per la protezione delle API

Le API RESTful moderne utilizzano JWT per l'autenticazione e l'autorizzazione. Ecco un flusso tipico:

  1. l'utente si autentica con nome utente e password.

  2. Il server verifica le credenziali e genera un JWT.

  3. Il client memorizza il token (solitamente in localStorage o sessionStorage).

  4. Ad ogni richiesta protetta, il client lo invia nell'Authorization Header.

  5. Il server verifica il JWT e concede o nega l'accesso.

Questo metodo elimina la necessità di mantenere sessioni sul server, migliorando scalabilità e sicurezza.

Protezione e best practies nell'uso di JWT

Anche se i JSON Web Tokens offrono numerosi vantaggi, è fondamentale adottare le migliori pratiche di sicurezza:

Utilizzare una chiave segreta forte

La chiave segreta utilizzata per firmare i token deve essere robusta e sicura. Evitiamo stringhe deboli come password123 e utilizziamo strumenti come openssl per generare una chiave forte:

openssl rand -base64 32

Impostare una scadenza adeguata

Evitare che un token sia valido per troppo tempo riduce i rischi in caso di furto del token stesso. Usiamo durate brevi (es. 15 minuti) e implementiamo un meccanismo di refresh token.

Utilizzare HTTPS

I JWT devono essere sempre trasmessi su HTTPS per prevenire attacchi di tipo Man-in-the-Middle (MITM).

Se si usa un cookie per memorizzare il token, assicuriamoci di configurarlo come HttpOnly e Secure:

res.cookie("token", jwtToken, { httpOnly: true, secure: true });

Implementare un sistema di revoca

Poiché i JSON Web Tokens sono stateless, il server non ha modo di invalidarli prima della loro scadenza. Un'opzione è mantenere una blacklist di token revocati.

Preferire RS256 invece di HS256

Quando possibile, usiamo algoritmi a chiave pubblica/privata (es. RS256) invece di chiavi simmetriche (HS256) per migliorare la sicurezza.

Conclusioni

Abbiamo visto come implementare JSON Web Tokens per autenticare e proteggere API RESTful. Abbiamo coperto la generazione, validazione e le best practices di sicurezza. Implementando correttamente i JWT, possiamo costruire applicazioni sicure e scalabili. Nella prossima lezione approfondiremo ulteriori strategie di sicurezza e best practices in OAuth 2.0 e JWT.

Ti consigliamo anche