Работает для HS256, HS384, HS512. Для RS256 нужен Public Key (PEM) — реализован через Web Crypto.
Сервер вычисляет HMAC-SHA256 от строки base64url(header).base64url(payload) с использованием секрета. Результат должен совпадать с третьей частью JWT. Если хоть один байт payload изменён — подпись не совпадёт.
httpOnly cookie: недоступен через JS → защита от XSS. localStorage: доступен через JS → любой XSS украдёт токен. Рекомендация: httpOnly Secure SameSite=Strict cookie.
Меняешь алгоритм в header на "alg":"none", убираешь подпись. Уязвимые библиотеки принимают такой токен без проверки. Никогда не доверяй алгоритму из самого токена — проверяй принудительно на сервере.
Сервер использует RS256 и публичный ключ известен. Атакующий меняет alg на HS256 и подписывает токен этим публичным ключом как HMAC-секретом. Уязвимые библиотеки принимают, т.к. подпись «верна». Фикс: явно указывать разрешённый алгоритм.
JWT с HS256 можно взломать перебором секрета офлайн — токен публичный. Секрет должен быть случайным и ≥ 256 бит (32 байта). openssl rand -hex 32 — правильный способ генерации.
Токен без поля exp действует вечно. Если утечёт — остановить невозможно (JWT stateless). Всегда устанавливай короткий TTL: 15 мин для access token, refresh token в httpOnly cookie.