Blog

laravel e jwt

Laravel e JWT: Realizzare un sistema di autenticazione

Tempo di lettura: 13 minuti

In questo tutorial realizzeremo un sistema di autenticazione completo con Laravel e Jwt (json web token), alla fine sarete in grado di realizzare una API REST sicura.

Laravel  rende tale operazione relativamente semplice e veloce  grazie ad una struttura già predisposta a realizzare tale funzionalità, e lo vedremo di seguito.

Laravel e JWT: Cosa è Laravel

Ciò si potrebbe definire in poche parole, come una boccata d’aria fresca.

Lasciatemi partire dalla mia esperienza personale. Negli ultimi dieci anni, sia per lavoro che per hobby, ho lavorato molto con PHP ed i suoi framework. Ne ho visti alcuni, rimanendo legato essenzialmente a Simphony. Quando ho scoperto Laravel, però, le cose sono cambiate del tutto.

Questo è un framework PHP, ovviamente orientato alla programmazione ad oggetti ed al pattern architetturale MVC (che se non conoscete consiglio caldamente di studiarvi) e all’eliminazione di uno dei nostri peggiori nemici, lo spaghetti code. Presenta, inoltre, un comodo sistema di bundles per “pacchettizzare” i nostri software (parliamo quindi di HMVC), in modo tale da creare applicazioni sempre più sofisticate e al tempo stesso facilmente manutenibili.

La sua storia comincia nel 2011, quando Taylor Otwell decide di “rendere lo sviluppo web più facile e divertente, perché è quello che amo fare”. Da allora di strada ne è stata fatta, nonostante siano passati solo poco meno di due anni.

Attualmente, infatti, il progetto è arrivato alla versione 7 e ha sicuramente tante buone carte da giocare. Anzi, ottime carte come un sistema di authentication facile da usare, un ORM già pronto (Eloquent) oppure un command line tool integrato (Artisan).

Laravel e JWT: Cosa è il json web token

Il JSON Web Token (JWT) è uno standard open (RFC 7519) che definisce uno schema in formato JSON per lo scambio di informazioni tra vari servizi.
Il token generato può essere firmato (con una chiave segreta che solo chi genera il token conosce) tramite l’algoritmo di HMAC, oppure utilizzando una coppia di chiavi (pubblica / privata) utilizzando gli standard RSA o ECDSA.

I JWT sono molto utilizzati per autenticare le richieste nei Web Services e nei meccanismi di autenticazione OAuth 2.0 dove il client invia una richiesta di autenticazione al server, il server genera un token firmato e lo restituisce al client che, da quel momento in poi, lo utilizzerà per autenticare le successive richieste.

Se volete saperne di più cliccate qui.

 

Installare laravel

Prima di installare Laravel dobbiamo installare Composer, ovvero il  tool che ci  permette di installare e aggiornare le librerie esterne in modo molto semplice. Scegliete la versione che fa al caso del vostro sistema operativo e procedete con l’installazione. Se siete sotto Windows scaricatevi il file .exe come in figura:

laravel e jwt

Ora ,come recita la documentazione ufficiale del nostro Framewok, avete due possibilità per installarlo. La prima procedura, più veloce, consiste nell’installare prima laravel/installer globalmente in modo tale da averlo disponibile sempre:

composer global require laravel/installer

quindi poi semplicemente :

laravel new namesite

sappiate però che questo richiede l’installazione nella vostra macchina di una versione di PhP non inferiore alla 7.3 altrimenti genera errore.

Per quanto riguarda la seconda procedura molto semplicemente digitate :

composer create-project --prefer-dist laravel/laravel namesite

 

Laravel e jwt: creiamo il progetto

Createvi una directoy nel vostro pc , aprite il terminale dirigetevi all’interno di essa e digitate:

composer create-project laravel/laravel laravel-jwt-auth --prefer-dist

attendete qualche istante, il tempo che venga scaricato il progetto Laravel.

Una volta terminato dirigetevi all’interno di questa, sempre da terminale, mediante:

cd laravel-jwt-auth

ora avviate il server:

php artisan serve

quindi aprite il browser all’indirizzo http://127.0.0.1:8000 , se tutto è andato bene vi si aprirà la home del vostro progetto.

laravel e jwt

Laravel e jwt: connessione con il db

Per poter lavorare con Laravel, framework php, è palese che nella vostra macchina sia installato un server locale come Xampp, Mamp o Wamp.

Io utilizzo Xampp, per cui lo avvio, apro la console in esso e vado a realizzare il db mediante i comandi:

mysql -u root -p

quando vi chiede la password inseritela o, se non la avete, date semplicemente invio:

a questo punto siamo pronti per creare il db, digitate:

CREATE DATABASE laravel_jwt;

verificate che in effetti sia stato creato:

SHOW databases;

se il db, appena creato risulta in lista è ok.

Configura il file  .env

Aprite il progetto Laravel, quindi il file .env, questo è un file di configurazione del framework. Dunque configurate la connessione al db creato precedentemente:

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

da terminale ora digitate:

php artisan migrate

ricordatevi di impartire i comandi sempre dall’interno della root principale del progetto.

Se vi da errore ricontrollate la configurazione della connessione al db, altrimenti aprite phpmyadmin e dovreste trovare il db creato con alcune tabelle come in figura:

 

Installa il package di autenticazione Jwt

Tymondesigns / jwt-auth è un pacchetto JWT di terze parti e consente l’autenticazione utente utilizzando il JSON Web Token in Laravel & Lumen in modo sicuro.

Da terminale spostati all’interno della root principale ed esegui:

composer require tymon/jwt-auth

Nota: se dovesse restituirvi un errore tipo:

Composer require runs out of memory. PHP Fatal error: Allowed memory size of 1610612736 bytes exhausted

allora prima di installare tymon/jwt-auth digitate ,sempre da terminale:

set COMPOSER_MEMORY_LIMIT=-1

n pratica aumentate memoria da composer.

 

finita l’installazione aprite il file config/app.php ed aggiungetelo  nel provider:

'providers' => [
    ....
    /*
     * Package Service Providers...
    */

    'Tymon\JWTAuth\Providers\LaravelServiceProvider',

    /*
     * Application Service Providers...
    */    

],
'aliases' => [
    ....
    'JWTAuth' => 'Tymon\JWTAuth\Facades\JWTAuth',
    'JWTFactory' => 'Tymon\JWTAuth\Facades\JWTFactory'
],

 

ora con la seguente istruzione pubblichiamo il pacchetto:

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

Per gestire la crittografia del token, genera una chiave segreta eseguendo il seguente comando:

php artisan jwt:secret

Abbiamo generato con successo la chiave segreta JWT ,la puoi controllarenel file .env:

...
JWT_SECRET=9fzOtDk9TYEEfGnpC5klZ5qBejbP5GpEeXnltgCPat7r34G4gGnbJgisqE41TNw9
...

Modifica il Model User

Nel framework MVC ,la lettera “M” sta per model. I model, o modelli, sono mezzi per gestire la logica dell’applicazione basate su tale architettura.

In Laravel il Model non è nient’altro che una classe la quale rappresenta la struttura logica e la relazione delle tabelle.

Ogni tabella ha un Model e ci consente di interagire con la stessa. Questi ti danno la possibilità ,quindi, di recuperare,inserire ed aggiornare le informazioni nella tabella relativa.

I model si trovano sotto la  directory App/Models.

Laravel ha già un  model User predefinito sotto App/Models/User.php, noi lo utilizzeremo per il processo di autenticazione, apritelo ed implementiamo il package jwt-auth :

<?php

    namespace App;

    use Illuminate\Notifications\Notifiable;
    use Illuminate\Foundation\Auth\User as Authenticatable;
    use Tymon\JWTAuth\Contracts\JWTSubject;

    class User extends Authenticatable implements JWTSubject
    {
        use Notifiable;

        /**
         * The attributes that are mass assignable.
         *
         * @var array
         */
        protected $fillable = [
            'name', 'email', 'password',
        ];

        /**
         * The attributes that should be hidden for arrays.
         *
         * @var array
         */
        protected $hidden = [
            'password', 'remember_token',
        ];

        public function getJWTIdentifier()
        {
            return $this->getKey();
        }
        public function getJWTCustomClaims()
        {
            return [];
        }
    }

 

  • getJWTIdentifier(): Riceve l’identificatore che verrà archiviato nella rivendicazione del soggetto del JWT.
  • getJWTCustomClaims(): Restituisce una matrice di valori chiave, contenente eventuali attestazioni personalizzate da aggiungere al JWT.

 

Aggiungi le routes per l’autenticazione

Prima di realizzare le routes per l’autenticazione creeremo un Middleware che abbia il compito di proteggere le stesse. Questo non è nient’altro che un meccanismo il quale serve a filtrare programmaticamente le richieste HTTP ricevute dalla vostra applicazione.

Ad esempio Laravel include un Middleware di default che verifica se l’utente è autenticato. Se non lo è, il Middleware reindirizzerà il visitatore alla schermata Login. Se l’utente invece lo è, alla richiesta, gli sarà permesso di continuare l’esecuzione come per intenzione.

Da terminale eseguite:

php artisan make:middleware JwtMiddleware

Una volta creato lo trovate sotto app/Http/Middleware/JwtMiddleware , apritelo e modificate come di seguito:

<?php

    namespace App\Http\Middleware;

    use Closure;
    use JWTAuth;
    use Exception;
    use Tymon\JWTAuth\Http\Middleware\BaseMiddleware;

    class JwtMiddleware extends BaseMiddleware
    {

        /**
         * Handle an incoming request.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Closure  $next
         * @return mixed
         */
        public function handle($request, Closure $next)
        {
            try {
                $user = JWTAuth::parseToken()->authenticate();
            } catch (Exception $e) {
                if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenInvalidException){
                    return response()->json(['status' => 'Token is Invalid']);
                }else if ($e instanceof \Tymon\JWTAuth\Exceptions\TokenExpiredException){
                    return response()->json(['status' => 'Token is Expired']);
                }else{
                    return response()->json(['status' => 'Authorization Token not found']);
                }
            }
            return $next($request);
        }
    }

Tale middleware estende Tymon\JWTAuth\Http\Middleware\BaseMiddleware, con lo stesso possiamo rilevare gli errori dei token e restituire tali codici  specifici ai nostri utenti.

Successivamente dovete registrarlo, aprite il file app/http/Kernel.php e digitate:

[...]
protected $routeMiddleware = [
    [...]
    'jwt.verify' => \App\Http\Middleware\JwtMiddleware::class,
];
[...]

bene siamo pronti per creare le rotte, aprite il file routes/api.php e modificate:

<?php

use App\Http\Controllers\DataController;
use App\Http\Controllers\UserController;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

/*
|--------------------------------------------------------------------------
| API Routes
|--------------------------------------------------------------------------
|
| Here is where you can register API routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| is assigned the "api" middleware group. Enjoy building your API!
|
*/

Route::post('register', [UserController::class,'register'])->name('register');
Route::post('login', [UserController::class,'authenticate'])->name ('login');
Route::get('open', [DataController::class,'open'])->name('open');

Route::group(['middleware' => ['jwt.verify']], function() {
    Route::get('user', [UserController::class,'getAuthenticatedUser'])->name('user');
    Route::get('closed', [DataController::class,'closed'])->name('closed');
});

Ho definito tutti i percorsi necessari per testare JWT.  Ho tenuto fuori dal Middleware group tutte quelle rotte che non necessitano di protezione.

Crea il controller per l’autenticazione

Nonostante Laravel permetta di definire alcuni comportamenti direttamente nel file routes.php, questo approccio non è scalabile. La soluzione perfetta per gestire i vari entry point delle nostre applicazioni è invece l’utilizzo dei controller.

Laravel ha previsto per questa tipologia di componente una cartella dedicata: app/Http/Controllers e una classe da estendere Illuminate\Routing\Controller.

Questo è una semplice classe che presenta diversi metodi pubblici. Ciascuno di questi ultimi viene associato ad una URL e ad un metodo HTTP. Per associare una URL ad un determinato controller si usa la sintassi NomeController@nomeMetodo.

Per il nostro esempio creeremo due controller: UserControllerDataController.

La UserControllerconterrà la logica di autenticazione, mentre il DataControllerrestituirà dati di esempio.

Crea i controller:

$ php artisan make:controller UserController 
$ php artisan make:controller DataController

una volta creati aprite UserController seguendo il percorso app / Http / Controllers / UserController.php :

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class UserController extends Controller
{
    //
}

ecco come si presenta, come si può notare è una classe php, modificate come di seguito:

<?php

    namespace App\Http\Controllers;

    use App\User;
    use Illuminate\Http\Request;
    use Illuminate\Support\Facades\Hash;
    use Illuminate\Support\Facades\Validator;
    use JWTAuth;
    use Tymon\JWTAuth\Exceptions\JWTException;

    class UserController extends Controller
    {
        public function authenticate(Request $request)
        {
            $credentials = $request->only('email', 'password');

            try {
                if (! $token = JWTAuth::attempt($credentials)) {
                    return response()->json(['error' => 'invalid_credentials'], 400);
                }
            } catch (JWTException $e) {
                return response()->json(['error' => 'could_not_create_token'], 500);
            }

            return response()->json(compact('token'));
        }

        public function register(Request $request)
        {
                $validator = Validator::make($request->all(), [
                'name' => 'required|string|max:255',
                'email' => 'required|string|email|max:255|unique:users',
                'password' => 'required|string|min:6|confirmed',
            ]);

            if($validator->fails()){
                    return response()->json($validator->errors()->toJson(), 400);
            }

            $user = User::create([
                'name' => $request->get('name'),
                'email' => $request->get('email'),
                'password' => Hash::make($request->get('password')),
            ]);

            $token = JWTAuth::fromUser($user);

            return response()->json(compact('user','token'),201);
        }

        public function getAuthenticatedUser()
            {
                    try {

                            if (! $user = JWTAuth::parseToken()->authenticate()) {
                                    return response()->json(['user_not_found'], 404);
                            }

                    } catch (Tymon\JWTAuth\Exceptions\TokenExpiredException $e) {

                            return response()->json(['token_expired'], $e->getStatusCode());

                    } catch (Tymon\JWTAuth\Exceptions\TokenInvalidException $e) {

                            return response()->json(['token_invalid'], $e->getStatusCode());

                    } catch (Tymon\JWTAuth\Exceptions\JWTException $e) {

                            return response()->json(['token_absent'], $e->getStatusCode());

                    }

                    return response()->json(compact('user'));
            }
    }

Metodo Authenticate

Questo tenta di accedere ad un utente e genera un token di autorizzazione se lo stesso viene trovato nel database. Genera un errore se l’utente non viene trovato o se si è verificata un’eccezione durante il tentativo di trovarlo.

Metodo register

Il metodo register convalida un input dell’utente e lo crea  se le credenziali dell’utente vengono convalidate. L’utente viene quindi passato a JWTAuthper generare un token di accesso per l’utente creato. In questo modo, l’utente non avrebbe bisogno di accedere per ottenerlo.

Metodo getAuthenticatedUser

Questo restituisce l’oggetto utente in base al token di autorizzazione che viene passato.

Avvia il server con il seguente comando:

php artisan serve

Prova l’API di autenticazione Laravel e jwt con Postman

Postman è un tool  utilissimo che consente di provare le nostre API in maniera molto più snella e semplice, evitando di realizzare  driver/stub per testare i nostri servizi.

Ti consiglio di scaricarlo ed installarlo, dunque aprilo ed inserisci:

Registrazione

Endpoint: 127.0.0.1:8000/api/register
Metodo: POST
Payload:

name: Test Man
email: test@email.com
password: secret
password_confirmation: secret

Login Utente

Endpoint: 127.0.0.1:8000/api/login
Metodo: POST
Payload:

email: test@email.com
password: secret

Accesso a rotta non protetta

Endpoint: 127.0.0.1:8000/api/open
metodo:GET

Accesso ad End Point protetto

Endpoint: 127.0.0.1:8000/api/closed
Metodo: GET
Payload:

Authorization: Bearer insert_user_token_here

Prova ad accedere ai dati protetti dal middleware utilizzando il token di autorizzazione.

Ottieni i dati utente autenticati

Endpoint: 127.0.0.1:8000/api/user
Metodo: GET
Payload:

Authorization: Bearer insert_user_token_here

Utilizza un token non valido per accedere ai dati di un utente

Endpoint: 127.0.0.1:8000/api/user
Metodo: GET
Payload:

Authorization: token fake

Accesso senza Token ad una rotta protetta

Endpoint: 127.0.0.1:8000/api/closed
metodo:GET

Conclusione

In questa guida, abbiamo esaminato il JWT e come utilizzarlo nelle applicazioni Laravel, impostato un controller per l’autenticazione e la registrazione dell’utente.

Avete anche definito un metodo per ottenere l’utente autenticato utilizzando il token generato ed, infine, visto come viene utilizzato per proteggere le nostre API e testato i dati di output utilizzando Postman.

Puoi utilizzare il JWT per proteggere i tuoi endpoint API a cui accederanno diversi utenti. Il JWT è un ottimo sistema per autenticare gli utenti.

Il codice sorgente dell’applicazione in questo articolo è disponibile su GitHub .

Se volete Approfondire le conoscenze su Laravel potete seguire il  corso completo su Udemy sempre scontato a 9.99/12.99 € , inoltre, nel momento in cui non foste soddisfatti, avete la possibilità di ottenere il rimborso completo dello stesso entro 30 giorni dalla data di acquisto!

Lucio Ticali

Chi è ?

Lucio Ticali è un Web & App developer con la passione per il web marketing,si occupa anche di tecniche di indicizzazione del sito e di promozione dello stesso (SEO e SEM).

Lascia la tua opinione