Отзыв токенов в системах, использующих JSON Web Token (JWT), остаётся одной из наиболее сложных задач из-за статeless-природы токенов. После выдачи JWT сервер не хранит состояние, а вся информация о сессии содержится внутри самого токена. Это упрощает масштабирование, но делает невозможным прямую инвалидизацию без дополнительных механизмов.
Библиотека jose предоставляет инструменты для подписи, проверки и шифрования JWT, JWS и JWE, однако механизм отзыва токенов не входит в её область ответственности. Реализация контроля актуальности токенов строится на уровне архитектуры приложения.
JWT после выпуска остаётся валидным до истечения срока действия
(exp), даже если пользователь уже вышел из системы или
токен скомпрометирован. Это создаёт фундаментальное ограничение:
Из этого вытекает необходимость внешних механизмов контроля.
Один из наиболее распространённых подходов — использование блоклиста (blacklist/denylist). Суть заключается в хранении списка токенов, которые более не считаются валидными.
При выдаче JWT в токен добавляется уникальный идентификатор:
jti (JWT ID) — уникальная строкаsub + iat + expПри отзыве токена его jti заносится в хранилище
блокировки.
Во время каждой проверки токена выполняется дополнительный шаг:
exp)jti в blocklist{
"sub": "user_123",
"iat": 1710000000,
"exp": 1710003600,
"jti": "c2f1a9e0-3b2f-4d9a-8c6a-9d1b5e8a7f44"
}
На практике используются:
Redis применяется чаще всего из-за TTL-логики: запись автоматически
удаляется после exp.
Key: blacklist:c2f1a9e0-3b2f-4d9a-8c6a-9d1b5e8a7f44
Value: revoked
TTL: 3600 секунд
Логика проверки дополняется запросом:
jti найден в Redis → токен недействителенНесмотря на простоту, модель имеет существенные недостатки:
При большом количестве пользователей и коротких токенах:
Каждая проверка токена становится не полностью локальной:
В микросервисной архитектуре необходимо:
Один из наиболее практичных подходов — сокращение времени жизни JWT до минимального значения (например, 5–15 минут).
Используется связка:
Refresh-токен хранится на сервере и может быть инвалидирован.
Архитектура:
Этот подход минимизирует необходимость blocklist.
Механизм ротации refresh-токенов усиливает безопасность.
Это позволяет:
Альтернативная модель — использование whitelist (allowlist).
В системе хранится список активных токенов или сессий:
Чаще используется не сам JWT, а:
В некоторых системах применяется модель introspection:
Сервер:
Этот подход характерен для OAuth2-архитектур.
Поле jti становится центральным элементом при реализации
отзывов.
Типовые сценарии:
При любом событии:
jti пользователя добавляются в
blocklistБиблиотека jose используется только для криптографической части:
jwtVerify — проверка подписи и структурыSignJWT — выпуск токеновdecodeJwt — чтение payload без проверкиПример проверки с дополнительной логикой:
import { jwtVerify } from 'jose'
async function verifyToken(token, secret, redisClient) {
const { payload } = await jwtVerify(token, secret)
const jti = payload.jti
if (await redisClient.get(`blacklist:${jti}`)) {
throw new Error('Token revoked')
}
return payload
}
Здесь видно, что ревокация реализуется вне библиотеки.
На практике используется комбинация методов:
Такой подход снижает нагрузку на хранилище и минимизирует риск использования отозванных токенов.
Выбор стратегии зависит от требований:
jti должен генерироваться как UUIDНаиболее частые проблемы:
jti в токенахТакие ошибки приводят к фактическому отсутствию механизма отзыва, несмотря на его формальное наличие.