Abilities у Sanctum - аналог OAuth-scopes: токен може робити лише те, що йому дозволено при створенні.
$token = $user->createToken('CI deploy', ['servers:read', 'servers:deploy'])->plainTextToken;
$readOnly = $user->createToken('Звіти в Google Sheets', ['reports:read'])->plainTextToken;
Без другого аргументу токен отримує ['*'] - усі можливості.
Перевірка в коді:
if ($request->user()->tokenCant('servers:deploy')) {
abort(403);
}
Перевірка middleware на маршрутах (аліаси реєструються в bootstrap/app.php):
->withMiddleware(function (Middleware $middleware): void {
$middleware->alias([
'abilities' => \Laravel\Sanctum\Http\Middleware\CheckAbilities::class,
'ability' => \Laravel\Sanctum\Http\Middleware\CheckForAnyAbility::class,
]);
})
Route::post('/servers/{server}/deploy', DeployController::class)
->middleware(['auth:sanctum', 'abilities:servers:deploy']); // потрібні всі перелічені
Route::get('/reports', ReportController::class)
->middleware(['auth:sanctum', 'ability:reports:read,admin']); // достатньо будь-якої
Головне правило: abilities обмежують токен, але не замінюють авторизацію користувача. Токен з servers:deploy дає право деплоїти лише ті сервери, до яких має доступ сам користувач. Перевірка - обидві:
public function deploy(Request $request, Server $server)
{
abort_unless($request->user()->tokenCan('servers:deploy'), 403);
$this->authorize('deploy', $server); // політика: чи це сервер користувача
}
Особливість для SPA: при сесійній автентифікації (Sanctum SPA) tokenCan() завжди повертає true - запит від власного фронтенду, обмежень токена немає. Тому логіка «що можна користувачу» має бути в політиках, а abilities - лише додаткове обмеження для токенів.
Практичні поради:
- принцип найменших прав: інтеграції видавати токени з мінімальним набором можливостей;
- читабельні назви -
ресурс:дія(orders:read,orders:write); - інтерфейс керування токенами для користувача: назва, можливості, дата останнього використання (
last_used_atSanctum оновлює автоматично), кнопка відкликання; - тести:
Sanctum::actingAs($user, ['orders:read'])- і перевірка, що запис заборонено.
Докладніше в документації: Laravel Sanctum: можливості токенів