When I first needed to add API authentication to a Laravel project, I looked at Passport and immediately felt overwhelmed. OAuth2 servers, clients, grants — it was a lot for what I needed. Then I found Sanctum. It took me about 20 minutes to get it working.
Sanctum is the right choice for most APIs. It handles token-based authentication simply and cleanly. Here is how to use it.
Getting started
In Laravel 11 and 12, Sanctum comes pre-installed. For older versions:
composer require laravel/sanctum
php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider"
php artisan migrateAdd the HasApiTokens trait to your User model:
use Laravel\Sanctum\HasApiTokens;
class User extends Authenticatable {
use HasApiTokens, HasFactory, Notifiable;
}The login endpoint
This is the endpoint your mobile app or frontend calls to get a token:
public function login(Request $request): JsonResponse {
$request->validate([
'email' => 'required|email',
'password' => 'required',
]);
if (!Auth::attempt($request->only('email', 'password'))) {
return response()->json([
'message' => 'These credentials do not match our records.'
], 401);
}
$user = $request->user();
$token = $user->createToken('api-token')->plainTextToken;
return response()->json([
'user' => $user,
'token' => $token,
]);
}The client stores this token and sends it with every future request in the Authorization header:
Authorization: Bearer 1|abc123...Protecting your routes
Route::middleware('auth:sanctum')->group(function () {
Route::get('/user', fn(Request $r) => $r->user());
Route::apiResource('posts', PostController::class);
Route::post('/logout', [AuthController::class, 'logout']);
});Logging out
public function logout(Request $request): JsonResponse {
$request->user()->currentAccessToken()->delete();
return response()->json(['message' => 'Logged out successfully']);
}Token abilities (optional but useful)
If you need different permissions for different tokens — say, a read-only token for a reporting dashboard:
$token = $user->createToken('reporting-dashboard', ['reports:read']);
// In your controller
if (!$request->user()->tokenCan('reports:read')) {
abort(403);
}When to use Passport instead
Sanctum is perfect for first-party apps — your own mobile app, your own SPA. If you need to let third-party developers authenticate on behalf of your users (like how apps connect to Twitter or GitHub), then you need Passport and full OAuth2.
For everything else, Sanctum is simpler and gets the job done.




