JWT: access и refresh токены

↑ 5.5 Аутентификация и доступ: Keycloak, SSO, ACL · ← Предыдущая · → Следующая

Обязательно~3 мин чтенияУровень: middle

Зачем это на собесе

JWT спрашивают везде: структура, что проверять, зачем refresh и как хранить.

Объяснение

Подробно серверная сторона — JWT Bearer: валидация токена, claims, срок жизни. Клиентская перспектива:

JWT = header.payload.signature (Base64Url). Payload (claims: sub, iss, aud, exp, iat, роли) читается любым; подпись защищает от подделки, но не скрывает содержимое.

function parseJwt(t: string) {
  const [, p] = t.split(".");
  return JSON.parse(decodeURIComponent(escape(atob(p.replace(/-/g, "+").replace(/_/g, "/")))));     // только для чтения claims; проверка подписи — на сервере
}
const { exp } = parseJwt(token); const expiresInMs = exp * 1000 - Date.now();
ТокенНазначениеСрокХранение
Accessдоступ к API (Authorization: Bearer)5–15 минутв памяти (переменная/стор)
Refreshполучение нового accessчасы–дниHttpOnly cookie (или защищённо на сервере в BFF)
ID token (OIDC)сведения о пользователе для клиентакороткийне отправляют в API

Обновление:

  • Проактивно: по таймеру за 30–60 секунд до exp (setTimeout, keycloak.updateToken(30)).
  • Реактивно: при 401 (см. интерсептор в Axios: инстансы и интерсепторы) с единым запросом обновления.
  • Ротация refresh-токена: каждый refresh выдаёт новый; повторное использование старого → отзыв всей цепочки (защита от кражи).
  • Выход: отзыв refresh на сервере (logout endpoint), очистка состояния и кэша Query.

Ограничения JWT:

  • Невозможно «отозвать» access до exp без списка отзыва/introspection — поэтому короткий срок.
  • Размер (заголовок Authorization в каждом запросе).
  • Не кладите чувствительные данные в payload.
  • Проверка exp на клиенте — только для UX; сервер решает.

Проверка на сервере: подпись (JWKS), iss, aud, exp, nbf, алгоритм (запрет none).

Нюансы и подводные камни

  • Смещение часов клиента: не полагайтесь на локальные часы точно (запас по времени).
  • Несколько вкладок одновременно обновляют токен: синхронизируйте (BroadcastChannel/Web Locks).
  • Потеря состояния при перезагрузке страницы: access в памяти → восстановление через refresh cookie (silent refresh).
  • Токен в URL попадает в логи и историю.

Практика

  1. Реализуйте проактивное и реактивное обновление токена с единым запросом.
  2. Синхронизируйте обновление между вкладками.
  3. Опишите поведение при истёкшем refresh.

Вопросы с ответами

Связанные темы