Багато API вимагають не статичний ключ, а короткоживучий токен доступу, який треба періодично отримувати й оновлювати.
Client Credentials - сервер звертається до API від імені свого застосунку, без участі користувача (інтеграції між системами):
final class WarehouseToken
{
public function get(): string
{
return Cache::remember('warehouse:access_token', now()->plus(minutes: 50), function () {
$response = Http::asForm()
->post(config('services.warehouse.token_url'), [
'grant_type' => 'client_credentials',
'client_id' => config('services.warehouse.client_id'),
'client_secret' => config('services.warehouse.client_secret'),
'scope' => 'stock:read',
])
->throw();
return $response->json('access_token');
});
}
}
Ключові моменти:
- кешувати токен на термін трохи менший за
expires_in(запас на годинники й тривалі запити). Запит нового токена на кожен виклик API - зайві затримки і можливе блокування за частотою; - конкурентне оновлення: коли токен закінчився, десяток воркерів одночасно підуть за новим. Захист - блокування (
Cache::lock('warehouse:token')) чиCache::flexibleдля фонового оновлення; - повтор при 401: токен могли відкликати раніше терміну - скинути кеш, отримати новий і повторити запит один раз:
Http::withToken($token->get())
->retry(2, 0, function ($exception, PendingRequest $request) use ($token) {
if (! $exception instanceof RequestException || $exception->response->status() !== 401) {
return false;
}
$request->withToken($token->refresh());
return true;
})
->get($url);
Токени від імені користувача (Authorization Code: доступ до Google Calendar користувача, його GitHub):
- зберігати access token і refresh token у базі, зашифрованими (каст
encrypted); - оновлювати access token через refresh token, коли закінчився термін, і зберігати новий refresh token, якщо провайдер його видав (багато провайдерів ротують refresh token при кожному використанні - старий перестає працювати);
- обробляти відкликання доступу (користувач відключив застосунок):
invalid_grant- позначити інтеграцію неактивною й попросити підключити знову; - у Laravel вхід через провайдерів і отримання токенів - Socialite.
Секрети клієнта (client_secret) - у .env/менеджері секретів, ніколи у фронтенді. Мінімальні scope - лише потрібні права.