Laravel Sanctum is a lightweight authentication package for SPAs (single-page applications), mobile apps, and simple APIs. Without needing deep knowledge of OAuth, you can issue and manage multiple API tokens per user.Sanctum solves two authentication problems:
Authentication mode
How it works
Primary use cases
API token authentication
Authorization: Bearer <token> header
Mobile apps, third-party integrations
SPA authentication
Session cookie + CSRF protection
First-party frontends (Vue, React, etc.)
Use SPA authentication when calling your API from your own SPA. Use API token authentication when mobile apps or third-party clients need to access your API. You can use either mode independently or both together.
Use the createToken() method to issue a token. Retrieve the plain-text token value from the plainTextToken property. The plain-text token is never stored in the database, so you must return it to the user immediately after creation.
use Illuminate\Http\Request;Route::post('/tokens/create', function (Request $request) { $token = $request->user()->createToken($request->token_name); return ['token' => $token->plainTextToken];})->middleware('auth');
The database stores a SHA-256 hashed version of the token.
use Laravel\Sanctum\Http\Middleware\CheckAbilities;use Laravel\Sanctum\Http\Middleware\CheckForAnyAbility;->withMiddleware(function (Middleware $middleware): void { $middleware->alias([ 'abilities' => CheckAbilities::class, // requires all abilities 'ability' => CheckForAnyAbility::class, // requires any one ability ]);})
Apply the middleware to your routes:
// Only tokens with both check-status and place-orders are allowedRoute::get('/orders', function () { // ...})->middleware(['auth:sanctum', 'abilities:check-status,place-orders']);// Tokens with either check-status or place-orders are allowedRoute::get('/orders', function () { // ...})->middleware(['auth:sanctum', 'ability:check-status,place-orders']);
// Delete all tokens$user->tokens()->delete();// Delete the token used in the current request$request->user()->currentAccessToken()->delete();// Delete a specific token$user->tokens()->where('id', $tokenId)->delete();
SPA authentication uses session cookies, so there is no need to issue or manage tokens. It is ideal when calling your API from a first-party frontend (Vue, React, Next.js, etc.).
SPA authentication requires the SPA and API to share the same top-level domain (subdomains are fine). Requests must include an Accept: application/json header as well as a Referer or Origin header.
Apply the auth:sanctum middleware to your routes. Unauthenticated requests will receive a 401 Unauthorized response. This single middleware handles both API token authentication and SPA authentication.
use Illuminate\Http\Request;// Protect a single routeRoute::get('/user', function (Request $request) { return $request->user();})->middleware('auth:sanctum');// Protect a group of routesRoute::middleware('auth:sanctum')->group(function () { Route::get('/profile', [ProfileController::class, 'show']); Route::put('/profile', [ProfileController::class, 'update']); Route::get('/posts', [PostController::class, 'index']);});
// routes/api.phpRoute::middleware('auth:sanctum')->group(function () { // Return current user data Route::get('/user', function (Request $request) { return $request->user(); }); // Revoke current token and log out Route::post('/logout', function (Request $request) { $request->user()->currentAccessToken()->delete(); return response()->json(['message' => 'Logged out successfully.']); }); // Log out from all devices Route::post('/logout/all', function (Request $request) { $request->user()->tokens()->delete(); return response()->json(['message' => 'Logged out from all devices.']); });});
Use Sanctum::actingAs() in your tests to authenticate a user and specify which abilities to grant.
Pest
PHPUnit
use App\Models\User;use Laravel\Sanctum\Sanctum;test('can retrieve task list', function () { Sanctum::actingAs( User::factory()->create(), ['view-tasks'] ); $response = $this->get('/api/tasks'); $response->assertOk();});test('token with all abilities can access the endpoint', function () { Sanctum::actingAs( User::factory()->create(), ['*'] ); $response = $this->get('/api/tasks'); $response->assertOk();});
use App\Models\User;use Laravel\Sanctum\Sanctum;public function test_task_list_can_be_retrieved(): void{ Sanctum::actingAs( User::factory()->create(), ['view-tasks'] ); $response = $this->get('/api/tasks'); $response->assertOk();}
# Install Sanctum and run migrationsphp artisan install:api
Add the HasApiTokens trait to your User model:
use Laravel\Sanctum\HasApiTokens;class User extends Authenticatable{ use HasApiTokens, HasFactory, Notifiable;}
Common API reference
// Issue a token$token = $user->createToken('token-name')->plainTextToken;// Issue a token with abilities$token = $user->createToken('token-name', ['read', 'write'])->plainTextToken;// Check abilities$user->tokenCan('read'); // true/false$user->tokenCant('write'); // true/false// Revoke tokens$user->tokens()->delete(); // all tokens$request->user()->currentAccessToken()->delete(); // current token$user->tokens()->where('id', $id)->delete(); // specific token
Choosing between API token auth and SPA auth
API token authentication: Use when clients without a session — such as mobile apps, third-party services, or CLI tools — need to access your API.
SPA authentication: Use when your first-party Vue, React, or Next.js frontend calls the API from the same domain (or subdomain). More secure and requires no token management.