laravel/sanctum
Laravel Sanctum is a lightweight authentication solution for Laravel SPAs and simple APIs. It supports session-based SPA auth and API token authentication, letting you secure first-party apps and issue personal access tokens with minimal setup.
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
config/auth.php to use the sanctum guard for your API routes. Sanctum automatically registers this guard when installed.auth:sanctum middleware in your routes/api.php or controller definitions.First use case: Enable SPA authentication for a frontend (e.g., Inertia or plain Vue/React) running on localhost:3000. Add that domain to stateful in config/sanctum.php, then use Sanctum::login() in your SPA to obtain a token (or rely on session-based authentication via CSRF-protected endpoints like /sanctum/csrf-cookie).
SPA Authentication Flow:
Use Laravel’s built-in CSRF cookie endpoint (GET /sanctum/csrf-cookie) followed by a POST to /login. Subsequent requests use session-based auth via auth:sanctum, ideal for Inertia or SPA deployments with same-origin or same-site cookies.
Token-Based APIs:
Generate personal access tokens using the Authenticatable model:
$token = $user->createToken('app-token', ['read:user'])->plainTextToken;
Protected routes use auth:sanctum middleware. Scope enforcement is added via scope:read:user or abilities([ 'read:user', 'write:user' ]).
Cross-Domain or Mobile Apps:
Use personal access tokens with appropriate scopes and expiration:
// Model must implement HasApiTokens
$token = $user->createToken('mobile-app', now()->addDays(7));
Stateful Domain Configuration:
Edit config/sanctum.php → stateful to include domains (e.g., ['api.yourapp.com', 'localhost:8080']) where session-based auth is acceptable.
Testing:
Use actingAs() with Sanctum’s PersonalAccessToken for testing token-protected endpoints:
$token = Sanctum::actingAs($user, ['*']);
CSRF Misconfigurations: Ensure APP_URL is correctly set in .env, and include SanctumMiddleware or use WithoutMiddleware for API route tests. Prior to v3.2.2, CSRF middleware toggles caused confusion—review middleware order.
Cookies vs Tokens: Use session-based auth (auth:sanctum) only for stateful domains. Otherwise, tokens must be sent via Authorization: Bearer {token} header.
Token Prefixes and Security: As of v3.2.6, tokens are prefixed (e.g., 1|abc123) and use crc32b. Do not rely on token obfuscation—always use HTTPS and validate scopes.
Expiration Handling: Use expires_at (added in v3.0.0) for scheduled token expiration. Prune expired tokens with:
php artisan sanctum:prune-expired
Debugging Authentication: Check if sanctum guard is configured in auth.php (not config/auth.php—it should be 'guards' => ['api' => ['driver' => 'sanctum']]]). Also verify HasApiTokens is used on your User model.
Middleware Order Matters: As seen in v3.3.0 changelog, middleware ordering affects authentication. Ensure VerifyCsrfToken is included where needed (e.g., SPA login flow), but not for pure API token endpoints.
Performance Tip: Sanctum uses a last_used_at column (configurable in v4.3.0) to update timestamps. Disable tracking if unused:
// in config/sanctum.php
'stateful' => [...],
'supports_tokens' => true,
'expiration' => null, // no expiry
'token_prefix' => '',
'last_used_at' => false,
Custom Authentication Logic: Implement Sanctum::$accessTokenAuthenticationCallback (v2.11.0+) for complex token validation (e.g., blacklisting, custom logic).
Migrations: The personal_access_tokens table uses morphs('tokenable'). Don’t rename your id column—v2.9.2 fixed issues where non-default primary keys broke plainTextToken generation.
How can I help you explore Laravel packages today?