OGOwnGate

Жизнь токена: почему Access Token на 24 часа — преступление

Выпустить JWT со сроком жизни на сутки или неделю — верный способ превратить утечку в катастрофу, которую невозможно остановить. Разбираем, почему Access Token должен жить 5–15 минут, и как правильно настроить ротацию Refresh Token.

Жизненный цикл JWT: короткоживущие токены и ротация Refresh Token

В девяти из десяти веб-приложений и микросервисных архитектур, созданных за последние пять лет, в конфигурационном файле авторизации красуется вот такая строчка:


{

  "jwt_access_token_ttl": "86400s", // 24 часа

  "jwt_refresh_token_ttl": "2592000s" // 30 дней

}

Разработчик, писавший этот код, рассуждал просто: *«Если поставить токен на 10 минут, пользователей будет постоянно выбрасывать из системы, саппорт завалят тикетами, а мобилка начнёт лагать. Поставим сутки — и никаких проблем!»*.

Проблем действительно нет. Ровно до того момента, пока этот токен впервые не утечёт.

Давайте разберёмся, почему Access Token со сроком жизни 24 часа — это бомба замедленного действия, и как нормальные инженеры балансируют между комфортом пользователей и реальной безопасностью.

---

Проклятие самодостаточности: почему JWT нельзя отозвать

В чём главная прелесть JSON Web Token (JWT)? Он не требует состояния (stateless).

Токен содержит внутри себя все данные: кто вы (sub), какие у вас права (roles), когда он выдан (iat) и когда протухнет (exp). Токен подписан асимметричным ключом (RS256 или Ed25519).

Любой ваш микросервис — от биллинга до профиля — может взять этот токен, проверить математическую подпись по публичному ключу и сказать: *«Да, токен валиден, добро пожаловать»*. Микросервису не нужно делать запрос в базу данных или обращаться к центральному серверу авторизации. Быстро, масштабируемо, надёжно.

Но в этом же кроется и фатальная уязвимость.

Представьте:

1. Ноутбук сотрудника заражён инфостилером, или токен попал в логи прокси-сервера из-за кривого заголовка;

2. Злоумышленник скопировал Access Token себе;

3. Вы заметили подозрительную активность, заблокировали сотрудника в Active Directory и сменили ему пароль.

Знаете, что произойдёт с украденным токеном? Ничего.

Микросервисы понятия не имеют, что сотрудника уволили или сменили ему пароль. Они не смотрят в Active Directory. Они просто проверяют математическую подпись токена и дату в поле exp. И пока 24 часа не истекут, злоумышленник будет спокойно скачивать базы клиентов, выгружать репозитории и дергать продакшн-API от имени скомпрометированного сотрудника.

---

Попытки починить проблему костылями

Когда до команды доходит осознание этой проблемы, начинаются судорожные попытки построить костыли:

Костыль 1. «Чёрные списки» (Blacklists) в Redis

Админы поднимают Redis и при каждом логауте записывают ID отозванного токена (jti). Теперь микросервис перед выполнением запроса идёт в Redis проверить, не отозван ли токен.

*Поздравляем: вы только что убили главную фичу JWT и вернулись к классическим тяжелым сессиям в общей базе данных, потеряв всю производительность.*

Костыль 2. Смена приватного ключа сервера

Паникующий техлид нажимает кнопку «Перегенерировать ключ подписи JWT».

*Итог: все 100% сотрудников компании в эту же секунду вылетают из всех рабочих сервисов с ошибкой авторизации, парализуя работу бизнеса.*

---

Как это устроено по стандарту: Access + Refresh Flow

Безопасная архитектура токенов строится на чётком разделении ролей (OAuth 2.0 Security BCP):


┌─────────────────────────────────────────────────────────────┐

│                       БРАУЗЕР / КЛИЕНТ                      │

│                                                             │

│  [Access Token] (в памяти JS)       [Refresh Token]         │

│  • Живёт 5–15 минут                 • Живёт дни/недели      │

│  • Для каждого запроса к API        • В защищённой HttpOnly │

│                                       SameSite Secure куке  │

└──────────────────────────┬──────────────────────┬───────────┘

                           │                      │

                  Каждые 5-15 мин                 │ Раз в 15 минут

                   к микросервисам                ▼ за новым Access

                           │             ┌────────────────────┐

                           ▼             │   [Шлюз OwnGate]   │

                   ┌──────────────┐      │                    │

                   │ Микросервисы │      │ Проверяет AD / MFA │

                   │ (Валидация   │      │ и ротирует токены  │

                   │  по JWKS)    │      └────────────────────┘

                   └──────────────┘

1. Access Token живёт 5–15 минут

Короткий срок жизни — это ваше окно допустимого риска. Даже если токен каким-то чудом перехватили из памяти браузера, через 5–10 минут он превратится в бесполезный мусор.

2. Токен не хранится в localStorage

Никогда не храните токены в localStorage или IndexedDB. Любая XSS-уязвимость на странице (например, в сторонней библиотеке аналитики) позволяет скрипту прочитать localStorage в одну строчку. Токен должен жить только в оперативной памяти рантайма.

3. Ротация Refresh Token (Refresh Token Rotation)

Каждый раз, когда приложение обращается к шлюзу OwnGate за новым Access Token, старый Refresh Token уничтожается, а клиенту выдаётся новая пара.

Если злоумышленник украл Refresh Token и попытался им воспользоваться, а через минуту легитимный клиент попробует обновиться старым токеном — шлюз мгновенно распознает конфликт (Reuse Detection) и аннулирует всю цепочку сессий, выбросив взломщика наружу.

---

Что в итоге

Безопасность авторизации — это не про выбор между «безопасно» и «удобно».

В шлюзе OwnGate короткоживущие Access-токены обновляются в фоновом режиме через Web Workers или защищённые куки абсолютно незаметно для сотрудника. Никто не видит мерцания экрана и не вводит пароль каждые 15 минут.

Но если инженера уволили или устройство попало не в те руки — доступ испаряется за считанные минуты, а не через сутки после катастрофы.

← Все статьи