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

Configurazione di LEMP Stack con Docker e Certificati SSL


Questo tutorial ti guida passo dopo passo nella configurazione di uno stack LEMP con Docker e Docker Compose, integrando la protezione SSL tramite Let’s Encrypt.

Prerequisiti

  • Un server Ubuntu con un utente non root abilitato a sudo e un firewall attivo.
  • Docker e Docker Compose installati.
  • Un dominio registrato con i record DNS configurati (A e www).

Fase 1: Configurazione del Server Web

Crea la directory di configurazione del progetto e il file nginx.conf:


mkdir -p webserver_www/nginx-conf
nano webserver_www/nginx-conf/nginx.conf

            

Inserisci il seguente blocco di configurazione:


server {
    listen 80;
    server_name your_domain www.your_domain;
    root /var/www/html;

    location ~ /.well-known/acme-challenge {
        allow all;
    }

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass php_fpm:9000;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    location ~ /\.ht {
        deny all;
    }
}

            

Nota: Ricordati di sostituire your_domain con il tuo dominio effettivo.

Fase 2: Definizione delle Variabili Ambientali

Crea un file .env per definire variabili sensibili:


nano webserver_www/.env

            

Inserisci i seguenti valori:


MYSQL_ROOT_PASSWORD=your_root_password
MYSQL_USER=your_php_fpm_user
MYSQL_PASSWORD=your_php_fpm_password
MYSQL_DATABASE=your_database

            

Fase 3: Configurazione di Docker Compose

Crea il file docker-compose.yml per definire i servizi:


version: '3'
services:
  db:
    image: mysql:8.0
    env_file: .env
    volumes:
      - dbdata:/var/lib/mysql
    networks:
      - app-network

  php_fpm:
    image: php:8.2-fpm
    volumes:
      - php_fpm:/var/www/html
    networks:
      - app-network

  nginx:
    image: nginx:1.21-alpine
    ports:
      - "80:80"
    volumes:
      - php_fpm:/var/www/html
      - ./nginx-conf:/etc/nginx/conf.d
    networks:
      - app-network

  certbot:
    image: certbot/certbot
    volumes:
      - certbot-etc:/etc/letsencrypt
      - php_fpm:/var/www/html
    command: certonly --webroot --webroot-path=/var/www/html --email you@example.com --agree-tos --no-eff-email --staging -d your_domain -d www.your_domain

volumes:
  dbdata:
  php_fpm:
  certbot-etc:

networks:
  app-network:
    driver: bridge

            

Fase 4: Configurazione Certificati SSL

Esegui il comando per ottenere i certificati:


docker-compose up -d certbot

            

Verifica la presenza dei certificati con:


docker-compose exec nginx ls -la /etc/letsencrypt/live

            

Fase 5: Modifica della Configurazione Nginx

Modifica nginx.conf per abilitare HTTPS:


server {
    listen 443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/your_domain/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your_domain/privkey.pem;
}

            

Fase 6: Rinnovo Automatico dei Certificati

Crea uno script di rinnovo:


#!/bin/bash
docker-compose run certbot renew && docker-compose kill -s SIGHUP nginx

            

Configura un cron job:


crontab -e
# Aggiungi la seguente riga
0 12 * * * /path/to/ssl_renew.sh >> /var/log/cron.log 2>&1

            

Installare Certificati SSL Let’s Encrypt su uno Stack LEMP

Questa guida approfondisce l’installazione di certificati SSL gratuiti forniti da Let’s Encrypt utilizzando Certbot e configurandoli su uno stack LEMP (Linux, Nginx, MySQL, PHP) in un server Ubuntu.

Prerequisiti

  • Un server Ubuntu configurato seguendo la guida di configurazione iniziale (documentazione ufficiale).
  • Un nome di dominio registrato con i record DNS correttamente configurati (A record per il dominio principale e il sottodominio www).
  • Nginx installato e configurato con blocchi server per il dominio.

Passaggi

1. Installare Certbot

Certbot può essere installato tramite Snap. Aggiorna Snap core ed elimina versioni precedenti di Certbot se necessario:


sudo snap install core; sudo snap refresh core
sudo apt remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

2. Configurare Nginx

Assicurati che Nginx sia configurato con il corretto blocco server, includendo la direttiva server_name:


server {
    server_name example.com www.example.com;
    ...
}

3. Configurare il Firewall

Permetti il traffico HTTPS tramite il profilo Nginx Full:


sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'

4. Ottenere un Certificato SSL

Esegui Certbot per ottenere e configurare automaticamente il certificato:


sudo certbot --nginx -d example.com -d www.example.com

5. Verificare il Rinnovo Automatico

Certbot configura automaticamente un timer per il rinnovo dei certificati. Verifica lo stato del timer:


sudo systemctl status snap.certbot.renew.service

Simula un rinnovo per verificare la configurazione:


sudo certbot renew --dry-run

Riferimenti