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

  • Payload

  • Signature

  • 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

    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 validateToken null $token

    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 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.

    6. 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