Работа с claims
Claims (утверждения) — это полезная нагрузка токена, те заявления, которые вы подписываете. Это руководство охватывает стандартные (зарегистрированные) claims, которые библиотека проверяет за вас, как добавлять собственные и как безопасно читать их обратно.
Установка claims
JwtPayload — это обычный ассоциативный массив claims. Стандартные (зарегистрированные)
claims используют короткие трёхбуквенные ключи; вы можете добавить к ним любые
собственные ключи по своему усмотрению:
use Flytachi\Jwt\Entity\JwtPayload;
$now = time();
$payload = new JwtPayload([
// стандартные (зарегистрированные) claims
'iss' => 'https://my-app.com', // издатель
'sub' => 'user-42', // субъект (о ком токен)
'aud' => 'https://api.my-app.com', // аудитория
'iat' => $now, // время выпуска
'nbf' => $now, // недействителен ранее
'exp' => $now + 3600, // истекает через один час
// пользовательские claims — всё, что сериализуется в JSON
'role' => 'admin',
'scopes' => ['orders:read', 'orders:write'],
]);Временные claims проверяются автоматически
Три зарегистрированных claim управляют окном валидности токена, и decode() проверяет
за вас все три:
| Claim | Значение | Отклоняется, когда |
|---|---|---|
exp |
Время истечения | текущее время (минус допуск) достигло или превысило exp |
nbf |
Недействителен ранее | nbf позже текущего времени (плюс допуск) |
iat |
Время выпуска | iat позже текущего времени (плюс допуск) |
Каждый из них необязателен — опустите exp, и токен никогда не истечёт (редко то, что
вам нужно). Все значения — это Unix-время (timestamp) в секундах.
Всегда устанавливайте exp
Токен без exp действителен вечно, поэтому утёкший токен нельзя вывести из
обращения по времени. Задайте короткий срок жизни (от минут до часа для токенов
доступа) и выпускайте новый токен, когда прежний истекает.
Учитывайте рассинхронизацию часов с помощью допуска (leeway)
Часы серверов расходятся на несколько секунд. decode() принимает третий аргумент,
leeway (в секундах), который расширяет окно приёма при каждой проверке времени — так
что токен, который только что истёк или чей nbf на секунду в вашем будущем, не будет
отклонён из-за крошечного расхождения:
use Flytachi\Jwt\JWT;
// Допускать до 60 секунд разницы в часах
$payload = JWT::decode($token, [$publicKey], leeway: 60);Держите leeway малым — десятки секунд. Большие значения фактически продлевают
жизнь каждого токена сверх его заявленного exp.
Чтение claims обратно
getClaim() читает один claim с необязательным значением по умолчанию, если он
отсутствует:
$userId = $payload->getClaim('sub'); // 'user-42'
$role = $payload->getClaim('role', 'guest'); // значение по умолчанию, если отсутствует
$scopes = $payload->getClaim('scopes', []); // ['orders:read', ...]
if (in_array('orders:write', $payload->getClaim('scopes', []), true)) {
// авторизован на запись заказов
}Нужен весь набор сразу — для логирования или пересылки? Используйте toArray():
$all = $payload->toArray();
// ['iss' => 'https://my-app.com', 'sub' => 'user-42', 'role' => 'admin', ...]getClaim никогда не бросает исключение на отсутствующем claim
Отсутствующий claim возвращает значение по умолчанию (null, если вы его не передали),
поэтому чтение безопасно. Проверяйте claims, которые вам необходимы, явно — например,
отклоняйте токен без sub.
Проверяйте прикладные claims самостоятельно
Помимо временных claims, смысл остаётся за вами. Проверяйте издателя, аудиторию и любой claim авторизации после декодирования:
use Flytachi\Jwt\JWTException;
$payload = JWT::decode($token, [$publicKey]);
if ($payload->getClaim('aud') !== 'https://api.my-app.com') {
throw new JWTException('Token audience mismatch.');
}
if ($payload->getClaim('role') !== 'admin') {
http_response_code(403);
exit('Admins only.');
}Связанное
- «Проверка через JWKS» — проверка
iss/audна сторонних токенах - «HMAC-токены» · «Асимметричные ключи»
- «Справочник API» —
JwtPayload, допуск (leeway) вdecode()