Autenticazione con JWT

Questo articolo esplora l’uso di JSON Web Token (JWT) per autenticare servizi RESTful. Tratteremo i principi, i vantaggi e gli svantaggi di JWT, con esempi pratici in PHP.

Prerequisiti

Si richiede familiarità con l’architettura RESTful, e basi di programmazione in PHP.

Introduzione

Il bisogno di limitare l’accesso a risorse specifiche agli utenti autenticati è comune sia per applicazioni web che API. JWT offre una soluzione sicura, stateless e scalabile, rispettando i principi RESTful.

Cos’è un JSON Web Token?

Un JWT è una stringa codificata che contiene tre sezioni principali:

  • Header: Contiene il tipo di token (JWT) e l’algoritmo di firma (ad esempio, HMAC-SHA256).
  • Payload: Include i claims, ovvero informazioni sull’utente come ID, ruoli e scadenza del token.
  • Signature: Una firma generata utilizzando una chiave segreta per garantire integrità e autenticità.

Esempio di JWT


        eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhZG1pbiIsInJvbGVzIjpbIlJPTEVfQURNSU4iLCJST0xFX1VTRVIiXSwiaWF0IjoxNjgwODg4MDAsImV4cCI6MTY4MDg5MTYwfQ.s6EoZQc9m3VfRu77E3J9PqjD5Ikg1N8d0Ilx_EBzYYQ
        

Autenticazione Stateless

In ambienti RESTful come micorservizi ed api delle applicazioni SPA, il server non mantiene stato tra richieste successive. JWT permette al client di inviare tutte le informazioni relative all’utente autenticato per ogni richiesta, evitando la gestione di sessioni lato server.

Vantaggi di JWT

  • Scalabilità: Riduce il carico sul server.
  • Efficienza: Le informazioni sono incluse nel token stesso.
  • Sicurezza: La firma garantisce che i dati non siano stati alterati.

Svantaggi di JWT

  • Compromissione della chiave: Se la chiave privata sul server con cui sono firmati i token viene scoperta, l’intero sistema è vulnerabile.
  • Revoca complessa: Non è possibile invalidare i token senza una blacklist.
  • Lunghezza del token: Può aumentare il carico di rete.

Implementazione in PHP

Generazione di un Token


        require 'vendor/autoload.php';

        use Firebase\JWT\JWT;

        $key = "your_secret_key";
        $payload = [
            "iss" => "example.com",
            "aud" => "example.com",
            "iat" => time(),
            "exp" => time() + 3600,
            "user_id" => 12345,
            "roles" => ["ROLE_ADMIN"]
        ];

        $jwt = JWT::encode($payload, $key, 'HS256');
        echo $jwt;
        

Validazione di un Token


        require 'vendor/autoload.php';

        use Firebase\JWT\JWT;
        use Firebase\JWT\Key;

        preg_match('/Bearer\s(\S+)/', $headers['Authorization'], $matches));
        $jwt = $matches[1];
        $key = file_get_contents('privateKey.pem');

        try {
            $decoded = JWT::decode($jwt, new Key($key, 'HS256'));
            print_r($decoded);
        } catch (Exception $e) {
            echo 'Token non valido: ', $e->getMessage();
        }
        
diagramma di sequenza uml jwt autenticazione
diagramma di sequenza uml jwt autenticazione

Riferimenti

Autenticazione Utente con le Sessioni

Introduzione

In un’applicazione web tradizionale, l’autenticazione degli utenti si basa sul meccanismo di sessione tra il server e il client, ovvero uno spazio di memoria a cui accede il server, spazio di memoria associato al client.
Il collegamento logico / il filo conduttore tra la sequenza di transazioni è l “id di sessione” generato dal webserver, memorizzato nei cookie del browser, ed inviato dal client nei cookies ad ogni richiesta.

Questo articolo analizza i passaggi principali di: login, verifica dello stato autenticato e logout. La descrizione è accompagnata da esempi di codice PHP.

Concetti chiave

Autenticazione: è il processo di controllo delle credenziali utente (username/password). L’autenticazione dell’utente ha successo se viene trovata una corrispondenza tra le credenziali inserite in fase di login con i dati salvati in fase di registrazione.

Autorizzazione: è il controllo dei diritti dell’utente di accedere a determinate risorse.

1. Login

Durante la fase di login, l’utente inserisce le proprie credenziali (nome utente e password) in un form HTML. Il server valida queste credenziali e, in caso di successo, avvia una sessione. Ecco i passaggi principali:

  1. Invio delle credenziali: Le credenziali vengono inviate al server tramite una richiesta HTTP POST.
  2. Validazione delle credenziali: Il server verifica le credenziali confrontandole con i dati memorizzati (es. in un database).
  3. Avvio della sessione: In caso di successo, il server avvia una sessione utilizzando session_start() e memorizza informazioni sull’utente autenticato nella superglobale $_SESSION.
<?php
// Pseudocodice per il login
session_start();

// Validazione delle credenziali
$username = $_POST['username'];
$password = $_POST['password'];

if (validate_credentials($username, $password)) {
    $_SESSION['user'] = [
        'id' => get_user_id($username),
        'username' => $username
    ];
    header('Location: dashboard.php');
    exit;
} else {
    echo 'Credenziali non valide.';
}
?>

2. Verifica dello Stato Autenticato

Ad ogni richiesta HTTP, il server verifica se l’utente è autenticato controllando i dati nella sessione. Questo processo garantisce che solo gli utenti autenticati possano accedere a risorse protette.

<?php
// Pseudocodice per proteggere una pagina
session_start();

if (!isset($_SESSION['user'])) {
    // Reindirizza l'utente alla pagina di login
    header('Location: login.php');
    exit;
}

// L'utente è autenticato, procedi con la logica della pagina
echo 'Benvenuto, ' . htmlspecialchars($_SESSION['user']['username']);
?>

Diagramma uml di sequenza
Diagramma uml di sequenza

3. Logout

Il logout termina la sessione dell’utente eliminando i dati memorizzati e distruggendo l’ID di sessione. Questo passaggio previene ulteriori accessi senza una nuova autenticazione.

<?php
// Pseudocodice per il logout
session_start();

// Elimina i dati della sessione
$_SESSION = [];

// Distrugge la sessione
session_destroy();

// Reindirizza alla pagina di login
header('Location: login.php');
exit;
?>

Considerazioni sulla Sicurezza

  • Abilita session.cookie_secure per trasmettere i cookie solo su connessioni HTTPS.
  • Usa session_regenerate_id() dopo il login per prevenire attacchi di session fixation.
  • Configura session.cookie_httponly per evitare accessi JavaScript ai cookie.