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

Autenticazione JWT con Laravel 11

Integrazione delle API Laravel JWT:test Postman per un'autenticazione sicura delle nostre applicazioni Web
Integrazione delle API Laravel JWT:test Postman per un'autenticazione sicura delle nostre applicazioni Web
Link copiato negli appunti

Nel corso di di questa guida relativa alle API REST di Laravel, esploreremo diverse pratiche fondamentali. La creazione di API RESTful sicure utilizzando JWT (JSON Web Token) nel framework, il testing delle stesse con Postman e la generazione dei token JWT nell'ambiente Laravel.

Inoltre, vedremo come sfruttare le API di Laravel per integrare l'autenticazione JWT in un'applicazione web basata sul framework PHP. Questi passaggi offrono una panoramica completa delle procedure con cui implementare e gestire le API RESTful con un livello di sicurezza avanzato.

Il Json Web Token (JWT)

JWT viene utilizzato per autorizzare e scambiare informazioni tra server e client in modo sicuro. Esso autentica le richieste in ingresso fornendo un ulteriore strato di sicurezza all'API REST. Il che lo rende una soluzione ottimale per garantire la sicurezza dei dati.

Quando un utente invia delle informazioni al server Web, come ad esempio nome utente e password, queste vengono trasmesse tramite richieste HTTP GET e POST. Il server le elabora, autentica l'utente, e genera un token JWT che viene restituito al client come risposta. Il token JWT conterrà le informazioni per permettere al client di accedere alle risorse protette dall'API REST in modo sicuro e autorizzato.

La struttura del JWT

I JSON Web Token contengono tre parti separate da punti (.) nella loro forma compatta.

  • intestazione (Header).
  • Carico utile (Payload).
  • Firma (Signature).

Il suo aspetto è simile a questo:

xxxxxx.yyyyyyy.zzzzzzzzzz

Laravel 11

Laravel è un framework PHP open source che offre un ambiente di sviluppo per la creazione di applicazioni web robuste e scalabili. Uno dei suoi punti di forza è l'architettura MVC (Model-View-Controller) che favorisce la separazione tra logica di business, presentazione e gestione delle richieste. Fornisce un ecosistema di strumenti integrati che semplificano attività come la gestione delle sessioni, l'autenticazione, l'interrogazione dei database e la gestione delle code. Inoltre, offre un robusto sistema di routing, facilitando la definizione delle rotte per le richieste HTTP. Utilizza Blade per la gestione dei template, con una sintassi chiara e potente per la creazione delle viste delle applicazioni web. Supporta poi l'utilizzo di librerie front-end moderne, semplificando l'integrazione di JavaScript e CSS. Oltre alle funzionalità di base, è noto per il suo approccio alla sicurezza, con funzionalità come la protezione CSRF (Cross-Site Request Forgery), la gestione delle autorizzazioni tramite middleware e crittografia dei dati.

Per poter utilizzare Laravel assicuratevi di aver scaricato ed installato l'ultima versione del Composer e di un Web server locale a vostra scelta come Xampp, Lamp o laragon. Nel corso del tutorial userò laragon.

Composer è uno strumento di gestione delle dipendenze per PHP che facilita la gestione delle librerie e dei pacchetti di terze parti. Utilizza un file denominato composer.json per dichiarare le dipendenze e consente di installarle o aggiornarle tramite riga di comando.

Installare Laravel 11

Aprite il terminale, fatelo puntare su una directory a piacere e digitate:

composer create-project laravel/laravel:^11.0 jwt_demo

In alternativa potete installare globalmente l'installer di Laravel:

composer global require laravel/installer
laravel new jwt_demo

Il database

Aprite il terminale di Laragon (o del vostro web server locale) e digitate:

Autenticazione jwt laravel11

mysql -u root -p

La -u sta per "user", nel mio caso root, e -p sta per password, nel mio caso vuota. Ora se tutto ok potete creare il database:

CREATE DATABASE jwt_demo;

Se tutto è andato bene digitate:

SHOW DATABASES;

dovreste vedere una lista di databases fra i quali l'ultimo creato, altrimenti ripetete le operazioni precedenti.

Configurare la connessione al database nel file .env

Aprite il progetto con il vostro IDE preferito, nella root principale configurate il file .env (environment, variabili ambiente del progetto):

...
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=jwt_demo
DB_USERNAME=root
DB_PASSWORD=
...

Aggiungere un utente al database

In Laravel, la gestione degli utenti è semplificata dalla presenza di una tabella utente predefinita. Essa contiene le informazioni essenziali degli utenti, come nome, email, password... Per creare questa tabella nel database MySQL e sfruttare le funzionalità di gestione degli utenti fornite da Laravel, è necessario eseguire alcuni passaggi.

Innanzitutto, assicurati di avere configurato correttamente il file .env del progetto con le credenziali di accesso al database. Questo file è cruciale per stabilire la connessione tra Laravel e il database. Successivamente, apri il terminale o il prompt dei comandi e spostati nella directory radice del progetto. Utilizza quindi il comando artisan di Laravel per la migrazione necessaria a creare la tabella utente nel database. Il comando da eseguire è:

php artisan migrate

Esso ha generato la tabella users nel database.

Installare e configurare il package JWT

tymondesigns/jwt-auth è un pacchetto JWT di terze parti e consente l'autenticazione dell'utente con il JWT in Laravel e Lumen. Da terminale digitate:

composer require tymon/jwt-auth

Pubblicate la configurazione del pacchetto digitando:

php artisan vendor:publish --provider="Tymon\JWTAuth\Providers\LaravelServiceProvider"

Questo comando ha generato il file config/jwt.php.

Non ci resta quindi che generare una chiave segreta per gestire la crittografia del token:

php artisan jwt:secret

Se aprite il file .env noterete la chiave segreta generata correttamente:

...
JWT_SECRET=f6mw17zx6TWkaZLer0shKqR8LEzg5Fr3xo9ayttaOFmRufJEUui0MYjzDnqXs7lP
...

Settaggio del model User

Laravel include di default un modello predefinito chiamato User. Esso può essere sfruttato per gestire l'autenticazione degli utenti nel framework. In questo passaggio, esploreremo come implementare il pacchetto jwt-auth nel modello User. Consentendo così l'utilizzo di JWT per l'autenticazione.

Per iniziare, è necessario definire il contratto Tymon\JWTAuth\Contracts\JWTSubject prima del modello User. Questo contratto richiede l'implementazione di due metodi: getJWTIdentifier(), che restituisce l'identificatore memorizzato nell'attestazione (payload) dell'oggetto JWT, e getJWTCustomClaims(), che restituisce un array associativo di valori chiave che rappresentano eventuali claim personalizzati da includere nel JWT. Apri il file app/Models/User.php e sostituisci il codice seguente con quello già presente nel file per implementare correttamente i metodi:

namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Tymon\JWTAuth\Contracts\JWTSubject;
class User extends Authenticatable implements JWTSubject
{
    use HasFactory, Notifiable;
    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];
    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];
    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }
    public function getJWTIdentifier()
    {
        return $this->getKey();
    }
    /**
     * Return a key value array, containing any custom claims to be added to the JWT.
     *
     * @return array
     */
    public function getJWTCustomClaims()
    {
        return [];
    }
}

Configurazione dell'autenticazione protetta

Per configurare correttamente l'utilizzo del driver JWT per l'autenticazione API in Laravel, è necessario aprire il file config/auth.php. In questo file è possibile impostare la guardia predefinita su api e specificare che essa utilizzi il driver JWT per l'autenticazione. Ecco come puoi eseguire questa configurazione:

  • apri il file config/auth.php nel progetto Laravel.
  • Trova la sezione relativa alle guardie (guards) e individua la guardia predefinita. Di solito è impostata su web.
  • Modifica la guardia predefinita in api, in modo che Laravel la utilizzi per gestire le richieste API.

'defaults' => [
    'guard' => env('AUTH_GUARD', 'api'),
    'passwords' => env('AUTH_PASSWORD_BROKER', 'users'),
],
'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],
    'api' => [
        'driver' => 'jwt',
        'provider' => 'users',
    ],
],

Con questa modifica, Laravel utilizzerà il driver JWT per gestire l'autenticazione delle richieste API, fornendo una soluzione sicura e scalabile per l'autenticazione basata su token JWT.

Il controller di autenticazione

Realizziamo il controller dove definiremo la logica principale del processo di autenticazione sicura. Da terminale digitate:

php artisan make:controller AuthController

Ora apritelo app/Http/Controllers/AuthController.php e modificate come di seguito:

namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Routing\Controller;
use App\Models\User;
class AuthController extends Controller
{
    /**
     * Create a new AuthController instance.
     *
     * @return void
     */
    public function __construct() {
        $this->middleware('auth:api', ['except' => ['login', 'register']]);
    }
    /**
     * Get a JWT via given credentials.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function login(Request $request){
        $validator = Validator::make($request->all(), [
            'email' => 'required|email',
            'password' => 'required|string|min:6',
        ]);
        if ($validator->fails()) {
            return response()->json($validator->errors(), 422);
        }
        if (! $token = auth()->attempt($validator->validated())) {
            return response()->json(['error' => 'Unauthorized'], 401);
        }
        return $this->createNewToken($token);
    }
    /**
     * Register a User.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function register(Request $request) {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|between:2,100',
            'email' => 'required|string|email|max:100|unique:users',
            'password' => 'required|string|confirmed|min:6',
        ]);
        if($validator->fails()){
            return response()->json($validator->errors()->toJson(), 400);
        }
        $user = User::create(array_merge(
            $validator->validated(),
            ['password' => bcrypt($request->password)]
        ));
        return response()->json([
            'message' => 'User successfully registered',
            'user' => $user
        ], 201);
    }
    /**
     * Log the user out (Invalidate the token).
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function logout() {
        auth()->logout();
        return response()->json(['message' => 'User successfully signed out']);
    }
    /**
     * Refresh a token.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function refresh() {
        return $this->createNewToken(auth()->refresh());
    }
    /**
     * Get the authenticated User.
     *
     * @return \Illuminate\Http\JsonResponse
     */
    public function userProfile() {
        return response()->json(auth()->user());
    }
    /**
     * Get the token array structure.
     *
     * @param string $token
     *
     * @return \Illuminate\Http\JsonResponse
     */
    protected function createNewToken($token){
        return response()->json([
            'access_token' => $token,
            'token_type' => 'bearer',
            'expires_in' => auth()->factory()->getTTL() * 60,
            'user' => auth()->user()
        ]);
    }
}

Middleware e metodi

Il middleware auth:api viene utilizzato all'interno del costruttore della classe. Non è possibile accedere ai metodi all'interno del controller di autenticazione senza disporre di un token valido. Inoltre possiamo passare nel middleware il nome delle funzioni escluse dall'obbligo del token.

Il metodo login consente l'autenticazione dell'utente mediante password ed email. In risposta genera un token di autorizzazione a patto che trovi l'utente all'interno del db. Nel caso contrario restituisce un errore. Con register inseriamo un nuovo utente nel db tramite dei campi con relativa validazione. Con logout cancelliamo il token dell'utente loggato.

Refresh crea un nuovo Token. userProfile esegue il rendering dei dati dell'utente connesso che abbia un token valido. createNewToken crea infineun nuovo token di autenticazione dopo la sua scadenza o eliminazione.

Definire le routes per l'autenticazione

Per gestire correttamente i percorsi di autenticazione per un'applicazione basata su autenticazione JWT in Laravel, è fondamentale definire i percorsi corrispondenti nell'API REST. Essi vengono serviti tramite il file delle rotte routes/api.php e utilizzano il prefisso api/. In particolare, i percorsi relativi all'autenticazione sono convenzionalmente indicati con auth/. In Laravel 11 il file api.php va abilitato mediante il comando:

php artisan install:api

Ad esempio, se desideri creare un endpoint per la registrazione degli utenti, il percorso completo sarà /api/auth/signup. Lo stesso principio si applica per gli altri percorsi legati all'autenticazione, come la login, il recupero password, la modifica del profilo e così via.

I percorsi di autenticazione

Per aggiungere correttamente questi percorsi di autenticazione, è necessario modificarli nel file delle rotte routes/api.php, non nel file web.php. Ecco un esempio di come potrebbe apparire il codice nel file routes/api.php per gestire la registrazione degli utenti:

return $request->user();
});
Route::group([
'middleware' => 'api',
'prefix' => 'auth'
], function ($router) {
Route::post('/login', [AuthController::class, 'login']);
Route::post('/register', [AuthController::class, 'register']);
Route::post('/logout', [AuthController::class, 'logout']);
Route::post('/refresh', [AuthController::class, 'refresh']);
Route::get('/user-profile', [AuthController::class, 'userProfile']);
});

Testare l'applicazione con Postman

Postman permette di testare, sviluppare e documentare le API. Consente agli utenti di inviare richieste HTTP a un server API e di ricevere e visualizzare le risposte dal server.

Con Postman è possibile testare vari tipi di richieste HTTP come GET, POST, PUT, DELETE, ecc., nonché inviare parametri, header e body nelle richieste. Inoltre, Postman offre funzionalità come la creazione di collezioni di richieste, la gestione delle variabili, la creazione di test automatizzati e la generazione di documentazione API.

Autenticazione con React ed il jwt di laravel 9

Registrazione

Aprite postman e nella barra degli indirizzi digitate l'indirizzo del metodo register definito nel file routes/api.php. Non vi scordate prima di servire l’applicazione:

Selezionate il metodo POST per la richiesta HTTP, quindi selezionate body, form-data e sotto inserite i nomi dei campi definiti nella request con i relativi valori. Una volta fatto cliccate "SEND". Se tutto ok verrà restituito un oggetto di tipo JSON con le info sull'utente registrato.

Login

Una volta aggiunto un utente al database è possibile testare la fase di autenticazione per verificare se viene creato correttamente un token di accesso. Prepariamoci a fare il login dell'utente creato precedentemente. Sempre in Postman aggiungete una nuova scheda cliccando su +. Questa volta nella barra degli indirizzi digitate http://127.0.0.1:8000/api/auth/login e selezionate ancora una volta il metodo POST:

Se tutto è andato a buon fine vi verranno restituite una serie di informazioni sempre in JSON, token compreso.

User Profile

Inserite ora l'indirizzo http://127.0.0.1:8000/api/auth/user-profile e selezionate il metodo GET. Cliccate su "Authorization", in "TYPE" scegliete "BEARER TOKEN" poi nel campo a destra incollate il token restituito in fase di login:

Se tutto è ok vi verrà restituito un oggetto con le info dell'utente loggato.

Refresh

Per aggiornare un token è necessario averne uno valido. Aggiungete una nuova scheda in Postman ed inserite l'indirizzo http://127.0.0.1:8000/api/auth/refresh. Selezionate questa volta il metodo POST, poi il resto rimane invariato rispetto a userProfile:

Ogni qualvolta cliccate "SEND" il token si aggiorna. Quello valido è ovviamente l'ultimo.

Logout

Aggiungete una nuova scheda in Postman. Digitate l'indirizzo http://127.0.0.1:8000/api/auth/logout, metodo POST, poi tutto rimane invariato rispetto al refresh purchè inseriate l’ultimo token aggiornato nell'apposito campo:

Fate click su SEND ed il token si cancellerà.

In conclusione

È essenziale testare accuratamente l'autenticazione JWT e le API che abbiamo creato utilizzando Postman. Questo passaggio serve per assicurarci che tutto funzioni come previsto lato server. Prima di integrare il sistema di autenticazione con un front-end.

Durante il testing con Postman, abbiamo inviato richieste di autenticazione utilizzando le credenziali degli utenti e verificato se i token JWT sono stati generati correttamente. Inoltre, abbiamo testato le rotte protette per garantire che i token JWT siano validi e consentano l'accesso alle risorse protette solo agli utenti autorizzati.

In un prossimo approfondimento scopriremo come integrare React con le nostre API Laravel per creare un'applicazione Web completa con un sistema di autenticazione sicuro basato su JWT.

Ti consigliamo anche