Ротация refresh token — это механизм обновления сессионного ключа перед его истечением. Необходимость в этом возникает при обнаружении признаков компрометации токена или по истечении заданного времени жизни, чтобы злоумышленник не мог использовать старый токен для доступа к ресурсам.

Ротация refresh token: механизм и необходимость

Механизм ротации работает следующим образом: клиент отправляет запрос на получение нового access token, прикладывая действующий refresh token. Сервер проверяет валидность старого токена, генерирует новый access token и выдаёт новый refresh token взамен старого.

Необходимость ротации обусловлена тем, что refresh token хранится долго (дни или месяцы). Если токен украден, злоумышленник имеет доступ к аккаунту на весь этот период. Ротация сокращает это окно уязвимости: после успешного обновления старый токен становится недействительным.

Важно понимать, что ротация должна быть реактивной (при подозрении на взлом) и проактивной (по таймауту). Без автоматической ротации система зависит от ручного сброса паролей при утечке.

Обнаружение повторного использования токена (Replay Attack)

Обнаружение Replay Attack строится на проверке уникальности каждого запроса с использованием refresh token. Сервер должен вести журнал использованных токен-пар или использовать nonce (одноразовые числа) для каждой ротации.

Если сервер получает запрос с токеном, который уже был использован ранее (даже если он формально ещё не истёк по времени), это сигнал о компрометации. Такой запрос должен быть отклонён с кодом 400 Bad Request или 401 Unauthorized.

Пример логики: при генерации нового refresh token сервер помечает старый как 'revoked' в базе данных или добавляет его ID в список использованных. Любая попытка предъявить этот ID снова блокируется.

Алгоритм безопасной ротации с проверкой на компрометацию

Шаг 1: Получение запроса. Клиент присылает refresh token.

Шаг 2: Валидация токена. Проверка подписи, времени жизни и статуса (active/revoked) в хранилище.

Шаг 3: Проверка на повторное использование. Перед генерацией нового токена сервер проверяет, не был ли этот конкретный токен уже использован для получения нового access token в текущей сессии или ранее. Если да — отклоняем запрос и логируем инцидент.

Шаг 4: Генерация пары. Создаётся новый refresh token и новый access token.

Шаг 5: Отзыв старого токена. Старый токен помечается как недействительный в базе данных или добавляется в список чёрного списка (revocation list).

Шаг 6: Ответ клиенту. Возвращаются новые токены и, при необходимости, флаг о том, что сессия обновлена.

Критерии выбора стратегии хранения и валидации токенов

Хранение: Refresh token должен храниться на сервере (stateful) или быть подписан так, чтобы можно было проверить его статус без обращения к БД (stateless), но с возможностью отзыва. Для отзывчивости лучше использовать базу данных или Redis с TTL.

Валидация: Проверка должна включать не только подпись токена, но и проверку на наличие в списке отозванных токенов. Это критично для защиты от Replay Attack.

Срок жизни: Refresh token должен иметь короткий срок жизни (например, 15 минут) с обязательной ротацией, либо очень долгий срок с жёсткой проверкой на повторное использование. Короткий срок снижает риск, но увеличивает нагрузку на сервер при частых обновлениях.

Шифрование: Токены должны быть зашифрованы при передаче (TLS 1.2+) и храниться в защищённом хранилище.

Типичные ошибки при реализации логики ротации

Ошибка 'Set-Cookie' без HttpOnly: Если refresh token передаётся через cookie, она должна иметь флаг HttpOnly, чтобы JavaScript не мог её прочитать и украсть.

Отсутствие проверки на повторное использование: Сервер выдаёт новый токен каждый раз, игнорируя факт, что старый уже использовался. Это классическая уязвимость Replay Attack.

Игнорирование статуса revoked: При проверке токена сервер не смотрит в базу данных на его статус 'revoked' и продолжает выдавать доступ.

Хранение refresh token в клиенте без защиты: Если токен хранится в localStorage, любой XSS-атака позволяет украсть его. Лучше использовать httpOnly cookies или хранить только access token в клиенте, а refresh token — строго на сервере.

Ограничения протоколов OAuth 2.0/OIDC в контексте безопасности

OAuth 2.0 не предписывает обязательную ротацию refresh token. Это решение на усмотрение разработчика, но для высокой безопасности оно необходимо.

OIDC добавляет возможности для отзыва токенов через endpoint /revoke-token, но требует правильной реализации клиентом и сервером.

Проблема 'token leakage': Если refresh token утекает в логи или метрики, злоумышленник может использовать его. Необходимо фильтровать логи от чувствительных данных.

Масштабируемость: Проверка на повторное использование требует хранения состояния (stateful). В распределённых системах это усложняет архитектуру, требуя общей БД или кэша между узлами.

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

Можно ли использовать refresh token без ротации?

Технически возможно, но это создаёт уязвимость. Если токен украден, злоумышленник имеет доступ до истечения срока действия токена (часто месяцы). Ротация сокращает этот риск.

Как часто нужно ротировать refresh token?

Частота зависит от политики безопасности. Рекомендуется ротация при каждом успешном входе или по таймауту (например, раз в 15 минут). Для корпоративных систем лучше использовать короткое время жизни токена.

Что делать, если refresh token был украден?

Немедленно отозвать токен через endpoint /revoke-token и потребовать от пользователя повторного входа. Это сгенерирует новый refresh token.

По теме