Introduzione a Laravel Sanctum
Nel panorama moderno dello sviluppo web, la gestione dell'autenticazione è diventata una sfida complessa. Con l'ascesa delle Single Page Applications (SPA) create con framework come Vue.js, React o Angular, e la necessità di fornire accesso a applicazioni mobile tramite API REST, gli sviluppatori si sono trovati a dover scegliere tra diverse strategie: i classici cookie di sessione o i token JWT (JSON Web Tokens).
Laravel Sanctum nasce per risolvere questo dilemma, offrendo un sistema leggero e flessibile che permette di gestire entrambi i mondi senza la complessità di implementazioni pesanti come Laravel Passport (che implementa l'intero standard OAuth2).
Perché scegliere Sanctum? Principalmente perché semplifica l'autenticazione per le SPA utilizzando i cookie di sessione di Laravel (che sono sicuri e resistenti agli attacchi XSS se configurati correttamente), pur permettendo l'emissione di "API Tokens" per i client che non supportano i cookie, come le app mobile o i servizi di terze parti.
Come Funziona Sanctum: I Due Approcci
Prima di immergerci nel codice, è fondamentale capire che Sanctum opera in due modalità distinte, a seconda di chi è il client.
1. Autenticazione basata su Cookie (SPA)
Quando l'applicazione frontend (es. Vue) risiede sullo stesso dominio (o sotto-dominio) del backend Laravel, Sanctum utilizza l'autenticazione basata su sessione. In questo scenario, non vengono scambiati token in ogni richiesta; Laravel utilizza i propri cookie di sessione e il middleware VerifyCsrfToken per garantire che le richieste siano legittime e provengano dall'utente autenticato.
2. Autenticazione basata su Token (API)
Per le app mobile o per l'accesso programmatico, Sanctum permette di generare token di accesso personali (Personal Access Tokens). Questi token sono stringhe casuali memorizzate nel database e inviate nell'header Authorization: Bearer {token} di ogni richiesta HTTP.
Installazione e Configurazione Iniziale
Il primo passo è l'installazione del pacchetto tramite Composer. Se stai utilizzando una versione recente di Laravel, è probabile che Sanctum sia già pre-installato, ma per sicurezza eseguiamo il comando:
composer require laravel/sanctum
Dopo l'installazione, dobbiamo pubblicare la configurazione e le migrazioni del database:
php artisan vendor:publish --provider="Laravel\\Sanctum\\SanctumServiceProvider"
php artisan migrate
Configurazione del Modello User
Affinché l'utente possa generare token, è necessario aggiungere il trait HasApiTokens al modello User. Questo trait fornisce i metodi necessari per creare e rimuovere i token di accesso.
<?php
namespace App\\Models;
use Illuminate\\Foundation\\Auth\\User;
use Illuminate\\Notifications\\Notifiable;
use Laravel\\Sanctum\\HasApiTokens;
class User extends Authenticatable
{
use HasApiTokens, Notifiable;
// Resto del modello...
}
In questo modo, l'oggetto User acquisisce la capacità di gestire i propri token tramite metodi come $user->createToken('token-name').
Implementazione dell'Autenticazione via Token
Vediamo ora come implementare un sistema di login che restituisca un token. Questo è il caso d'uso classico per le App Mobile o i client esterni.
Creazione del Controller di Autenticazione
Creiamo un controller per gestire il login. L'idea è validare le credenziali e, se corrette, generare un token unico per l'utente.
<?php
namespace App\\Http\\Controllers\\Api;
use App\\Http\\Controllers\\Controller;
use Illuminate\\Http\\Request;
use App\\Models\\User;
use Illuminate\\Support\\Facades\\Hash;
use Illuminate\\Validation\\ValidationException;
class AuthController extends Controller
{
public function login(Request $request)
{
$request->validate([
'email' => 'required|email',
'password' => 'required',
'device_name' => 'required', // Utile per identificare da quale dispositivo viene il token
]);
$user = User::where('email', $request->email)->first();
if (!$user || !Hash::check($request->password, $user->password)) {
throw ValidationException::withMessages([
'email' => ['Le credenziali fornite sono errate.'],
]);
}
// Creazione del token. Il device_name permette all'utente di revocare token specifici in futuro.
$token = $user->createToken($request->device_name)->plainTextToken;
return response()->json([
'access_token' => $token,
'token_type' => 'Bearer',
]);
}
public function logout(Request $request)
{
// Revoca il token corrente utilizzato per l'autenticazione
$request->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Logout effettuato con successo']);
}
}
Protezione delle Rotte
Per proteggere le rotte API, utilizzeremo il middleware auth:sanctum. Questo middleware verifica se la richiesta contiene un token valido o se l'utente è autenticato tramite sessione.
// routes/api.php
use App\\Http\\Controllers\\Api\\AuthController;
use Illuminate\\Support\\Facades\\Route;
Route::post('/login', [AuthController::class, 'login']);
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', function (Request $request) {
return $request->user();
});
Route::post('/logout', [AuthController::class, 'logout']);
});
Autenticazione per SPA (Stateful)
L'autenticazione per SPA è diversa perché non vogliamo che il frontend gestisca manualmente i token (evitando di salvarli in localStorage, dove sono vulnerabili agli attacchi XSS). Sanctum utilizza invece i cookie di sessione.
Passaggi per la configurazione SPA
- Middleware: Aggiungi il middleware
EnsureFrontendRequestsAreStatefulal gruppoapinel fileapp/Http/Kernel.php(o nel provider di configurazione nelle versioni più recenti di Laravel). - Configurazione CORS: Nel file
config/cors.php, impostasupports_credentials => trueper permettere l'invio dei cookie tra frontend e backend. - Dominio di sessione: Nel file
.env, impostaSESSION_DOMAIN=.tuodominio.comper assicurare che il cookie sia condiviso tra i sottodomini.
Il flusso CSRF
Per prevenire gli attacchi Cross-Site Request Forgery, Sanctum richiede che l'app frontend effettui prima una richiesta a un endpoint speciale: /sanctum/csrf-cookie.
Il flusso è il seguente:
- Il client chiama
GET /sanctum/csrf-cookie. - Laravel invia un cookie CSRF.
- Il client effettua la richiesta di login inviando il token CSRF nell'header
X-XSRF-TOKEN. - Se le credenziali sono corrette, Laravel avvia una sessione standard.
Esempi Pratici e Casi d'Uso
Caso 1: App Mobile (React Native/Flutter)
In questo scenario, l'utente inserisce email e password. L'app invia i dati a /api/login, riceve il plainTextToken e lo salva nel SecureStore del dispositivo. Ogni richiesta successiva includerà l'header Authorization: Bearer {token}.
Caso 2: Dashboard Aziendale (Vue.js + Laravel)
Qui l'app Vue e l'API Laravel condividono lo stesso dominio. L'app chiama /sanctum/csrf-cookie, poi effettua il login tramite POST /login (rotta web standard). Il browser gestisce automaticamente i cookie di sessione, rendendo l'esperienza utente fluida e sicura.
Caso 3: Gestione di Token Multipli
Immaginiamo un utente che accede da PC, Tablet e Smartphone. Grazie a createToken($deviceName), possiamo mostrare all'utente una lista di dispositivi connessi e permettergli di revocare l'accesso solo al Tablet se smarrito:
// Revoca tutti i token tranne quello attuale
$user->tokens()->where('id', '!=', $user->currentAccessToken()->id)->delete();
Errori Comuni e FAQ
"Unauthenticated" nonostante il token sia corretto
Questo è l'errore più frequente. Spesso accade perché:
- L'header
Accept: application/jsonnon è stato inviato. Senza questo header, Laravel potrebbe tentare di reindirizzare l'utente alla pagina di login web invece di restituire un errore 401 JSON. - Il middleware
auth:sanctumnon è applicato alla rotta.
Dove salvare il token nel frontend?
Mai in localStorage per le app web, a causa del rischio XSS. Per le SPA, usa l'autenticazione stateful di Sanctum. Per le app mobile, usa i sistemi di storage sicuro forniti dal sistema operativo (es. Keychain su iOS, EncryptedSharedPreferences su Android).
Qual è la differenza tra Sanctum e Passport?
Passport è un server OAuth2 completo. È necessario se devi permettere a terze parti di accedere ai dati dei tuoi utenti (come quando un sito permette di "Accedere con Google"). Sanctum è invece ideale per l'autenticazione interna della tua stessa applicazione.
Prossimi Passi
Ora che hai implementato l'autenticazione di base, puoi approfondire i seguenti temi per rendere la tua applicazione professionale:
-
Abilità dei Token (Token Abilities): Sanctum permette di assegnare permessi specifici ai token. Ad esempio, puoi creare un token che può solo "leggere" i dati ma non "scriverli":
$user->createToken('token-name', ['post:read'])->plainTextToken; -
Gestione dell'Espirazione: Configura la durata dei token nel file
config/sanctum.phpper aumentare la sicurezza. -
Integrazione con Laravel Fortify: Per una gestione ancora più robusta di registrazione, reset password e verifica email, considera l'uso di Laravel Fortify in combinazione con Sanctum.
-
Testing: Scrivi test automatizzati utilizzando
Sanctum::actingAs()per simulare utenti autenticati durante i tuoi test di integrazione.
L'autenticazione è il cuore della sicurezza di ogni applicazione. Utilizzare uno strumento standardizzato e supportato ufficialmente come Sanctum riduce drasticamente la superficie di attacco e accelera i tempi di sviluppo.