Laravel Sanctum is the simplest way to protect an API. It covers two common cases: token login for mobile apps and third-party clients, and cookie login for your own single-page app on the same domain.

Install Sanctum#

In Laravel 11 and 12, one command installs Sanctum, publishes its migration and creates routes/api.php:

php artisan install:api

Then add the HasApiTokens trait to your User model.

Issue tokens for mobile and external clients#

Create a login route that checks the credentials and returns a token:

Route::post('/login', function (Request $request) {
    $credentials = $request->validate([
        'email' => ['required', 'email'],
        'password' => ['required'],
    ]);

    if (! Auth::attempt($credentials)) {
        return response()->json(['message' => 'Invalid credentials'], 401);
    }

    $token = $request->user()->createToken('mobile', ['orders:read']);

    return ['token' => $token->plainTextToken];
});

The client sends it on every request as Authorization: Bearer <token>.

Protect routes#

Route::middleware('auth:sanctum')->group(function () {
    Route::get('/orders', [OrderController::class, 'index']);
    Route::post('/logout', fn (Request $r) => $r->user()->currentAccessToken()->delete());
});

Limit what a token can do#

Abilities give each token only the access it needs. Check them where it matters:

if (! $request->user()->tokenCan('orders:read')) {
    abort(403);
}

For a Vue or Nuxt front end on the same domain, skip tokens. Call /sanctum/csrf-cookie first, then log in normally. Sanctum uses the session cookie, so there is no token to store in the browser.

Security checklist#

  • Serve the API over HTTPS only.
  • Add rate limiting to the login route.
  • Set token expiry in config/sanctum.php.
  • Delete tokens on logout and when a password changes.
  • Never store tokens in localStorage for your own web app; use cookie login instead.