Laravel Sanctum vs Passport nel 2026: Autenticazione API e Domande da Colloquio

Confronto tra Laravel Sanctum e Passport per l'autenticazione API nel 2026. Esempi pratici di codice, autenticazione SPA, implementazione OAuth2 e domande frequenti nei colloqui tecnici.

Laravel Sanctum vs Passport nel 2026: Autenticazione API e Domande da Colloquio

Laravel Sanctum e Passport rispondono a esigenze diverse in materia di autenticazione API. La scelta del pacchetto sbagliato porta a complessità inutili o a vulnerabilità di sicurezza. Questa guida analizza entrambi i pacchetti con esempi di codice pratici e domande reali da colloquio tecnico.

Decisione Rapida

Sanctum gestisce l'autenticazione SPA e token API semplici. Passport implementa OAuth2 completo con authorization code, client credentials e refresh token. La maggior parte delle applicazioni necessita solo di Sanctum.

Laravel Sanctum vs Passport: Differenze Fondamentali

Sanctum fornisce un'autenticazione leggera basata su token, progettata per applicazioni first-party. Il pacchetto utilizza l'autenticazione tramite cookie di sessione per le SPA e Personal Access Token per app mobile e API semplici.

Passport implementa la specifica OAuth2 completa, inclusi authorization server, client credentials grant e autenticazione machine-to-machine. Questa complessità ha senso per applicazioni che devono autorizzare l'accesso di terze parti.

| Caratteristica | Sanctum | Passport | |----------------|---------|----------| | Caso d'uso principale | SPA, App Mobile, API Semplici | OAuth2 Third-Party, Machine-to-Machine | | Tipo di token | Token hash semplici | JWT con scope OAuth2 | | Auth Sessione | Sì (basata su cookie) | No | | Grant OAuth2 | Nessuno | Specifica completa | | Dimensione pacchetto | Minimale | Significativa | | Configurazione | Semplice | Complessa |

Implementare Sanctum per l'Autenticazione SPA

L'autenticazione SPA con Sanctum si basa sui cookie di sessione Laravel invece che sui token API. Frontend e backend devono condividere lo stesso dominio di primo livello affinché funzioni.

config/sanctum.phpphp
return [
    'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', sprintf(
        '%s%s',
        'localhost,localhost:3000,127.0.0.1,127.0.0.1:8000,::1',
        env('APP_URL') ? ','.parse_url(env('APP_URL'), PHP_URL_HOST) : ''
    ))),

    'expiration' => null, // I token non scadono mai per default

    'middleware' => [
        'verify_csrf_token' => App\Http\Middleware\VerifyCsrfToken::class,
        'encrypt_cookies' => App\Http\Middleware\EncryptCookies::class,
    ],
];

La SPA deve chiamare l'endpoint del cookie CSRF prima di effettuare richieste autenticate. Questo stabilisce la sessione e imposta il cookie XSRF-TOKEN.

javascript
// Frontend: Inizializzare la protezione CSRF prima del login
async function initializeAuth() {
    await fetch('/sanctum/csrf-cookie', {
        credentials: 'include'
    });
}

async function login(email, password) {
    await initializeAuth();
    
    const response = await fetch('/api/login', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'X-XSRF-TOKEN': getCookie('XSRF-TOKEN'),
            'Accept': 'application/json'
        },
        credentials: 'include',
        body: JSON.stringify({ email, password })
    });
    
    return response.json();
}

Autenticazione con Token API Sanctum

Le applicazioni mobile e le integrazioni di terze parti utilizzano Personal Access Token invece dei cookie di sessione. Sanctum memorizza questi token come hash SHA-256 nel database.

app/Http/Controllers/AuthController.phpphp
namespace App\Http\Controllers;

use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Hash;
use Illuminate\Validation\ValidationException;

class AuthController extends Controller
{
    public function createToken(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'password' => 'required',
            'device_name' => 'required',
        ]);

        $user = User::where('email', $request->email)->first();

        if (! $user || ! Hash::check($request->password, $user->password)) {
            throw ValidationException::withMessages([
                'email' => ['Le credenziali fornite non sono corrette.'],
            ]);
        }

        // Token con abilities (scope)
        $token = $user->createToken(
            $request->device_name,
            ['read', 'write'] // Abilities opzionali
        );

        return response()->json([
            'token' => $token->plainTextToken,
            'expires_at' => null // Configurare in sanctum.php
        ]);
    }

    public function revokeToken(Request $request)
    {
        // Revocare il token corrente
        $request->user()->currentAccessToken()->delete();

        return response()->json(['message' => 'Token revocato']);
    }
}

Le route vengono protette con il middleware auth:sanctum. Le abilities del token vengono verificate usando il metodo tokenCan.

routes/api.phpphp
use Illuminate\Support\Facades\Route;

Route::middleware('auth:sanctum')->group(function () {
    Route::get('/user', function (Request $request) {
        return $request->user();
    });

    Route::post('/posts', function (Request $request) {
        // Verificare se il token ha l'ability write
        if (! $request->user()->tokenCan('write')) {
            abort(403, 'Token non autorizzato alla scrittura');
        }

        return Post::create($request->validated());
    });
});

Configurare Laravel Passport per OAuth2

Passport richiede una configurazione più elaborata ma offre funzionalità OAuth2 complete. L'installazione crea tabelle nel database per client, token e refresh token.

bash
composer require laravel/passport
php artisan passport:install

Il comando passport:install genera le chiavi di crittografia e crea i client Personal Access e Password Grant.

app/Models/User.phpphp
namespace App\Models;

use Laravel\Passport\HasApiTokens;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use HasApiTokens;

    // ...
}

Le route di Passport vengono registrate nell'AuthServiceProvider:

app/Providers/AuthServiceProvider.phpphp
namespace App\Providers;

use Laravel\Passport\Passport;
use Illuminate\Support\ServiceProvider;

class AuthServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        Passport::tokensExpireIn(now()->addDays(15));
        Passport::refreshTokensExpireIn(now()->addDays(30));
        Passport::personalAccessTokensExpireIn(now()->addMonths(6));
    }
}

OAuth2 Password Grant con Passport

Il Password Grant permette alle applicazioni first-party di ottenere token con username e password. Viene comunemente utilizzato per le app mobile.

app/Http/Controllers/OAuth/TokenController.phpphp
namespace App\Http\Controllers\OAuth;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use App\Http\Controllers\Controller;

class TokenController extends Controller
{
    public function issueToken(Request $request)
    {
        $request->validate([
            'email' => 'required|email',
            'password' => 'required',
        ]);

        $response = Http::asForm()->post(config('app.url') . '/oauth/token', [
            'grant_type' => 'password',
            'client_id' => config('passport.password_client_id'),
            'client_secret' => config('passport.password_client_secret'),
            'username' => $request->email,
            'password' => $request->password,
            'scope' => '*',
        ]);

        if ($response->failed()) {
            return response()->json([
                'error' => 'Credenziali non valide'
            ], 401);
        }

        return $response->json();
    }
}

Client Credentials Grant per Machine-to-Machine

Il Client Credentials Grant è ideale per la comunicazione server-to-server dove non è richiesta l'interazione utente.

php
// Middleware per Client Credentials
Route::middleware(['client'])->group(function () {
    Route::get('/api/external/data', function () {
        return response()->json([
            'data' => ExternalData::all()
        ]);
    });
});

L'applicazione client si autentica con Client ID e Secret:

php
// Servizio esterno: richiedere token
$response = Http::asForm()->post('https://api.example.com/oauth/token', [
    'grant_type' => 'client_credentials',
    'client_id' => 'client-id',
    'client_secret' => 'client-secret',
    'scope' => 'read-data',
]);

$token = $response->json()['access_token'];

// Chiamare l'API con il token
$data = Http::withToken($token)
    ->get('https://api.example.com/api/external/data')
    ->json();

Scope dei Token per Permessi Granulari

Sia Sanctum che Passport supportano gli scope per limitare i permessi dei token. Passport definisce gli scope nell'AuthServiceProvider:

app/Providers/AuthServiceProvider.phpphp
use Laravel\Passport\Passport;

public function boot(): void
{
    Passport::tokensCan([
        'read-posts' => 'Leggere i post',
        'write-posts' => 'Creare e modificare post',
        'delete-posts' => 'Eliminare post',
        'admin' => 'Accesso amministratore completo',
    ]);

    Passport::setDefaultScope([
        'read-posts',
    ]);
}

Le route possono quindi richiedere scope specifici:

routes/api.phpphp
Route::middleware(['auth:api', 'scope:write-posts'])->group(function () {
    Route::post('/posts', [PostController::class, 'store']);
    Route::put('/posts/{post}', [PostController::class, 'update']);
});

Route::middleware(['auth:api', 'scopes:read-posts,write-posts'])->group(function () {
    // Richiede ENTRAMBI gli scope
    Route::get('/posts/drafts', [PostController::class, 'drafts']);
});

Pronto a superare i tuoi colloqui su Laravel?

Pratica con i nostri simulatori interattivi, flashcards e test tecnici.

Considerazioni sulla Sicurezza nell'Autenticazione Token

La gestione sicura dei token richiede diverse misure di protezione. La rotazione dei token previene l'uso prolungato di credenziali compromesse.

app/Http/Controllers/TokenController.phpphp
public function refreshToken(Request $request)
{
    $user = $request->user();
    $currentToken = $user->currentAccessToken();
    
    // Revocare il vecchio token
    $currentToken->delete();
    
    // Creare nuovo token con le stesse abilities
    $newToken = $user->createToken(
        $currentToken->name,
        $currentToken->abilities
    );
    
    return response()->json([
        'token' => $newToken->plainTextToken,
        'message' => 'Token rinnovato con successo'
    ]);
}

Per una maggiore sicurezza, configurare le scadenze dei token:

config/sanctum.phpphp
return [
    'expiration' => 60 * 24, // 24 ore in minuti
    
    // Rimuovere automaticamente i token scaduti
    'prune_after' => 7, // giorni
];

Lo scheduler può pulire automaticamente i token scaduti:

app/Console/Kernel.phpphp
protected function schedule(Schedule $schedule): void
{
    $schedule->command('sanctum:prune-expired --hours=24')->daily();
}

Domande da Colloquio sull'Autenticazione API Laravel

I colloqui tecnici per sviluppatori Laravel spesso valutano la comprensione dei concetti di autenticazione. Le seguenti domande e risposte coprono gli argomenti principali.

Domanda: Quando scegliere Sanctum rispetto a Passport?

Sanctum è la scelta giusta per applicazioni first-party: SPA che girano sullo stesso dominio dell'API, app mobile sviluppate dallo stesso team e requisiti semplici di token API. Passport è necessario quando serve funzionalità OAuth2: applicazioni di terze parti che necessitano accesso, Authorization Code Flow per servizi esterni, Client Credentials per comunicazione server-to-server o rotazione dei Refresh Token.

Domanda: Come funziona il meccanismo di protezione CSRF nell'autenticazione SPA di Sanctum?

Nell'autenticazione SPA, Sanctum utilizza sessioni e cookie Laravel. Il processo inizia con una richiesta a /sanctum/csrf-cookie, che imposta un cookie XSRF-TOKEN. La SPA legge questo cookie e invia il valore nell'header X-XSRF-TOKEN con ogni richiesta autenticata. Laravel valida questo token contro il valore memorizzato in sessione. Questo protegge dal Cross-Site Request Forgery, poiché altri domini non possono leggere il cookie.

Domanda: Quali sono le implicazioni di sicurezza dei Personal Access Token?

I Personal Access Token funzionano come password con validità illimitata. Le misure di sicurezza includono: scope limitati per ogni token, scadenze dei token, memorizzazione sicura lato client, possibilità di revoca immediata, logging di tutti gli utilizzi dei token e rotazione regolare dei token.

Domanda: Come implementare il Rate Limiting per l'autenticazione API?

Il Rate Limiting protegge da attacchi brute-force e abuso dell'API:

app/Providers/RouteServiceProvider.phpphp
use Illuminate\Cache\RateLimiting\Limit;
use Illuminate\Support\Facades\RateLimiter;

public function boot(): void
{
    RateLimiter::for('api', function (Request $request) {
        return Limit::perMinute(60)->by(
            $request->user()?->id ?: $request->ip()
        );
    });

    RateLimiter::for('auth', function (Request $request) {
        return Limit::perMinute(5)->by(
            $request->ip()
        );
    });
}

Domanda: Come testare endpoint API autenticati?

Laravel fornisce il metodo actingAs per i test con Sanctum e Passport:

tests/Feature/ApiTest.phpphp
use App\Models\User;
use Laravel\Sanctum\Sanctum;

public function test_authenticated_user_can_access_profile(): void
{
    $user = User::factory()->create();
    
    Sanctum::actingAs($user, ['read']);
    
    $response = $this->getJson('/api/user');
    
    $response->assertOk()
        ->assertJson(['email' => $user->email]);
}

public function test_token_without_scope_cannot_write(): void
{
    $user = User::factory()->create();
    
    Sanctum::actingAs($user, ['read']); // Nessuno scope 'write'
    
    $response = $this->postJson('/api/posts', [
        'title' => 'Test Post'
    ]);
    
    $response->assertForbidden();
}

Configurare l'Autenticazione Multi-Guard

Applicazioni complesse possono richiedere più meccanismi di autenticazione simultaneamente. Laravel permette di definire guard multipli:

config/auth.phpphp
return [
    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'sanctum',
            'provider' => 'users',
        ],
        'admin-api' => [
            'driver' => 'passport',
            'provider' => 'admins',
        ],
    ],
    
    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Models\Admin::class,
        ],
    ],
];

Le route possono quindi utilizzare guard specifici:

routes/api.phpphp
Route::middleware('auth:api')->group(function () {
    // Route protette da Sanctum per utenti normali
});

Route::prefix('admin')->middleware('auth:admin-api')->group(function () {
    // Route protette da Passport per amministratori
});

Best Practice per Ambienti di Produzione

Il deployment dell'autenticazione API in ambienti di produzione richiede considerazioni aggiuntive. HTTPS è obbligatorio per tutte le richieste che trasmettono token. Le variabili d'ambiente devono memorizzare le configurazioni sensibili.

.envphp
SANCTUM_STATEFUL_DOMAINS=app.example.com,api.example.com
SESSION_DOMAIN=.example.com

# Passport
PASSPORT_PRIVATE_KEY="..."
PASSPORT_PUBLIC_KEY="..."

Il monitoraggio e il logging degli eventi di autenticazione aiutano a rilevare attacchi:

app/Listeners/LogAuthenticationEvent.phpphp
namespace App\Listeners;

use Illuminate\Auth\Events\Login;
use Illuminate\Support\Facades\Log;

class LogAuthenticationEvent
{
    public function handle(Login $event): void
    {
        Log::info('Login utente', [
            'user_id' => $event->user->id,
            'ip' => request()->ip(),
            'user_agent' => request()->userAgent(),
        ]);
    }
}

Gli sviluppatori Laravel che implementano l'autenticazione API dovrebbero studiare approfonditamente la documentazione ufficiale di Sanctum e Passport. La scelta tra i due pacchetti dipende dai requisiti specifici dell'applicazione.

Passez à la pratique !

Conclusione

Laravel Sanctum e Passport rispondono a requisiti di autenticazione diversi. Sanctum offre una soluzione semplice ma sicura per SPA e app mobile con autenticazione token first-party. Passport implementa OAuth2 completo per scenari che richiedono autorizzazione di terze parti o comunicazione machine-to-machine.

La scelta dovrebbe basarsi sui requisiti effettivi: Sanctum per la maggior parte delle applicazioni, Passport solo quando la funzionalità OAuth2 è indispensabile. Entrambi i pacchetti richiedono configurazione attenta delle scadenze dei token, degli scope e del rate limiting per implementazioni pronte per la produzione.

Gli sviluppatori dovrebbero comprendere i meccanismi di protezione CSRF nell'autenticazione SPA, implementare la rotazione dei token e scrivere test completi per tutti i percorsi di autenticazione. Queste competenze sono rilevanti non solo per il lavoro quotidiano ma anche come componente importante dei colloqui tecnici per posizioni Laravel.

Condividi

Articoli correlati