HMAC-токены
HMAC — это самый простой способ использования JWT: одна секретная строка подписывает и проверяет. Обращайтесь к нему, когда один и тот же сервис и выпускает, и проверяет токены. Впервые здесь? Начните с «Быстрого старта».
Подпись с помощью секрета
encode() принимает JwtPayload и PrivateKey. Для HMAC материалом ключа служит
просто ваша секретная строка:
use Flytachi\Jwt\JWT;
use Flytachi\Jwt\Entity\JwtPayload;
use Flytachi\Jwt\Entity\PrivateKey;
$token = JWT::encode(
new JwtPayload([
'sub' => 'user-42',
'iat' => time(),
'exp' => time() + 3600,
]),
new PrivateKey('my-shared-secret', 'HS256')
);Проверка тем же секретом
decode() принимает токен и список PublicKey. Для HMAC вы передаёте ровно один —
верификатор использует первый ключ в массиве и игнорирует любой kid:
use Flytachi\Jwt\JWT;
use Flytachi\Jwt\Entity\PublicKey;
$payload = JWT::decode($token, [new PublicKey('my-shared-secret', 'HS256')]);
echo $payload->getClaim('sub'); // user-42Только один ключ для HMAC
decode() выбирает первый PublicKey в списке для любого токена HS* — он никогда
не смотрит на kid. Передавайте только один секрет. Выбор из нескольких ключей — это
функция только для асимметричных ключей; см. «Проверка через JWKS».
Выбор стойкости хеша
Три HMAC-алгоритма различаются только базовым SHA-хешем. Подписывающая и проверяющая стороны должны согласовать его — алгоритм привязан к ключу с обеих сторон.
| Алгоритм | Хеш | Размер подписи |
|---|---|---|
HS256 |
SHA-256 | 32 байта |
HS384 |
SHA-384 | 48 байт |
HS512 |
SHA-512 | 64 байта |
// Более стойкий хеш — всё остальное идентично
$token = JWT::encode(
new JwtPayload(['sub' => 'user-42']),
new PrivateKey('my-shared-secret', 'HS512')
);
$payload = JWT::decode($token, [new PublicKey('my-shared-secret', 'HS512')]);HS256 — это стандартный выбор, и он вполне надёжен, когда ваш секрет длинный и
случайный. HS384/HS512 добавляют запас при незначительных затратах CPU.
Генерация надёжного секрета
HMAC-секрет должен быть высокоэнтропийным — относитесь к нему как к паролю, а не как к парольной фразе:
openssl rand -base64 32Загружайте его из окружения, никогда из исходного кода:
$secret = getenv('JWT_SECRET')
?: throw new RuntimeException('JWT_SECRET is not set');
$token = JWT::encode(
new JwtPayload(['sub' => 'user-42', 'exp' => time() + 3600]),
new PrivateKey($secret, 'HS256')
);Обработка сценариев отказа
Каждый отказ — неверный секрет, подделанный токен, истёкший срок — приходит как одно
JWTException:
use Flytachi\Jwt\JWTException;
try {
$payload = JWT::decode($token, [new PublicKey($secret, 'HS256')]);
} catch (JWTException $e) {
// "Signature verification failed." / "Token has expired (exp)." / ...
http_response_code(401);
exit($e->getMessage());
}Один секрет, две возможности
Поскольку HMAC симметричен, любой, у кого есть секрет, может выпускать токены, а не только проверять их. Если вам нужно, чтобы третьи стороны могли проверять, но не могли подделывать, используйте вместо этого асимметричные ключи.
Связанные материалы
- Асимметричные ключи — RSA и ECDSA, когда проверяющие не должны подписывать
- Работа с claims — срок действия,
nbf, допуск, произвольные данные - Справочник API —
encode(),decode(), объекты ключей