laravel/sanctum
Laravel Sanctum is a lightweight authentication package for Laravel, ideal for SPAs and simple APIs. It supports cookie-based session auth for first-party SPAs and API tokens for personal access tokens, with minimal configuration and Laravel-first integration.
Installation:
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrate
personal_access_tokens table.Configure Middleware:
Add Sanctum’s middleware to app/Http/Kernel.php:
'api' => [
\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
'throttle:api',
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
For API routes, use auth:sanctum middleware.
First Use Case:
// Frontend (e.g., React/Vue)
const response = await fetch('/api/user', {
headers: { 'Authorization': `Bearer ${token}` }
});
// Laravel Controller
public function user(Request $request) {
return $request->user(); // Authenticated user
}
Key Files:
config/sanctum.php: Configure stateful domains, token expiration, and guards.app/Models/User.php: Ensure HasApiTokens trait is used.Generating Tokens:
// For a User model
$token = $user->createToken('app-name')->plainTextToken;
createToken() with a descriptive name (e.g., mobile-app, admin-dashboard).Revocating Tokens:
$user->tokens()->where('name', 'app-name')->delete();
Token Scopes:
$token = $user->createToken('admin')->scopes(['manage']);
authorize:manage).Stateful (SPAs):
stateful domains in config/sanctum.php:
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,127.0.0.1')),
EnsureFrontendRequestsAreStateful middleware to validate CSRF tokens for frontend requests.Stateless (Mobile/APIs):
auth:sanctum middleware without stateful checks.Authorization: Bearer <token> header.// In AppServiceProvider@boot()
Sanctum::getAccessTokenFromRequestUsing(function ($request) {
return $request->bearerToken() ?: $request->cookie('sanctum');
});
X-Auth-Token).$user = User::factory()->create();
Sanctum::actingAs($user);
$response = $this->withHeaders([
'Authorization' => 'Bearer ' . $user->createToken('test')->plainTextToken,
])->get('/api/endpoint');
CSRF Token Mismatches:
XSRF-TOKEN cookie is set.EnsureFrontendRequestsAreStateful middleware is applied.sanctum.stateful_domains in config and frontend meta tags.Token Expiration:
config/sanctum.php:
'expiration' => now()->addDays(30),
last_used_at tracking (v4.3.0+) to invalidate stale tokens:
Sanctum::enableTokenTracking(); // In AppServiceProvider
Database Indexes:
personal_access_tokens (v4.2.0+). Ensure your DB supports them.Token Prefix Collisions:
Middleware Order:
EnsureFrontendRequestsAreStateful before auth:sanctum in your middleware stack.Token Validation Errors:
sanctum.token_blacklist table if tokens are revoked but still valid.Bearer <60-character-token>.Logging:
config/logging.php:
'channels' => [
'sanctum' => [
'driver' => 'single',
'path' => storage_path('logs/sanctum.log'),
'level' => 'debug',
],
],
Common Issues:
Authorization header.XSRF-TOKEN cookie.throttle:api) is active.Custom Token Models:
HasApiTokens for custom token logic:
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable {
use HasApiTokens;
public function createCustomToken($name) {
return $this->createToken($name)->tap(function ($token) {
$token->forceFill(['custom_field' => 'value']);
});
}
}
Token Events:
// In EventServiceProvider
protected $listen = [
\Laravel\Sanctum\Events\TokenCreated::class => [
\App\Listeners\LogTokenCreation::class,
],
];
Custom Guards:
AuthServiceProvider:
Sanctum::guard('custom', function () {
return new CustomGuard();
});
Token Metadata:
$token = $user->createToken('app', ['read'], 30); // 30-minute expiry
$token->metadata = ['device' => 'mobile'];
$token->save();
Token Lookup:
crc32b for checksums (v3.3.0+). Ensure your DB indexes support this.Sanctum::useTokenCache(function ($token) {
return Cache::remember("sanctum-{$token->id}", now()->addMinutes(5), function () use ($token) {
return $token->user;
});
});
Database Optimization:
Schema::table('personal_access_tokens', function (Blueprint $table) {
$table->index(['tokenable_id', 'tokenable_type']);
$table->index('created_at');
});
Token Storage:
HttpOnly cookies or secure backend storage.Sanctum::statefulDomain('yourdomain.com');
Sanctum::cookie($token, 'sanctum', now()->addDays(30));
Rate Limiting:
Route::middleware(['throttle:60,1', 'auth:sanctum'])->get('/api/endpoint');
Sensitive Data:
user-123). Use generic names like mobile-app.
How can I help you explore Laravel packages today?