Laravel cookbook · Intermediate

Issue scoped API tokens with Sanctum

Integrations need long-lived API access with limited permissions that can be revoked.

Create a free account to save this page, take notes and track your progress. Sign in

Approach

Let users create personal access tokens with explicit abilities and an expiry, protect routes with auth:sanctum plus ability middleware, and show the plain token only once.

Solution

<?php
// app/Http/Controllers/ApiTokenController.php
namespace App\Http\Controllers;

use Illuminate\Http\Request;

class ApiTokenController extends Controller
{
    public function store(Request $request)
    {
        $data = $request->validate([
            'name' => ['required', 'string', 'max:50'],
            'abilities' => ['required', 'array'],
            'abilities.*' => ['in:orders:read,orders:write,reports:read'],
        ]);

        $token = $request->user()->createToken($data['name'], $data['abilities'], now()->addDays(90));

        return response()->json(['token' => $token->plainTextToken], 201);   // shown once
    }

    public function destroy(Request $request, int $tokenId)
    {
        $request->user()->tokens()->whereKey($tokenId)->delete();

        return response()->noContent();
    }
}
<?php
// routes/api.php
use App\Http\Controllers\OrderController;
use Illuminate\Support\Facades\Route;

Route::middleware('auth:sanctum')->group(function () {
    Route::get('/orders', [OrderController::class, 'index'])->middleware('ability:orders:read');
    Route::post('/orders', [OrderController::class, 'store'])->middleware('ability:orders:write');
});

Pitfalls

  • Tokens with ['*'] abilities for every integration.
  • No expiry, so leaked tokens work forever; also prune expired tokens (sanctum:prune-expired).
  • Logging the plain token or storing it unhashed elsewhere.

Variations

  • For browser SPAs on the same site, use Sanctum's cookie-based session authentication instead of tokens.
  • For third-party apps acting on behalf of users, use OAuth (Laravel Passport).

Further reading: Sanctum API tokens

Reference: https://laravel.com/docs/13.x/sanctum#api-token-authentication

More Laravel recipes

Was this page helpful?