JWT обновлялся не полностью после миграции сервиса
Симптом
После переноса старого сервиса на отдельный домен и базу данных пользователи начали периодически вылетать из системы.
Контекст
Сервис отделяли от общей инфраструктуры, поэтому одновременно менялись домен, база данных и переменные окружения CI. Пользовательский интерфейс продолжал работать до истечения access token, а затем не всегда мог получить новую пару токенов.
Корневая причина
Во frontend-логике обновления токенов заменялся access_token, но не
refresh_token. Следующий цикл обновления использовал старый refresh token и
завершался неуспешно.
Проблему усиливали две ошибки конфигурации: имена переменных в CI не совпадали с именами, которые читал backend, а отсутствующее значение незаметно заменялось коротким значением по умолчанию для refresh token. В результате поведение зависело от окружения и проявлялось как случайный logout.
Ошибочное предположение
Мы предполагали, что механизм обновления JWT на frontend уже работает корректно, а переменные окружения либо передаются, либо ошибка сразу становится очевидной. Ни одно из предположений не было закреплено проверкой контракта между клиентом, backend и CI.
Обнаружение
Первым сигналом стали обращения пользователей после миграции. Раньше проблему могли обнаружить два автоматических сигнала:
- интеграционная проверка полного цикла обновления пары access/refresh token;
- запуск backend без обязательной переменной окружения, который должен завершаться ошибкой, а не переходить на значение по умолчанию.
Исправление
Мы исправили frontend-обработку так, чтобы при обновлении сохранялись оба токена, и убрали значения по умолчанию для обязательных JWT-переменных окружения. Несовпадение имён переменных в CI и backend также было устранено.
Теперь отсутствие ключевой настройки должно проявляться при запуске сервиса, а не через случайные logout пользователей спустя некоторое время.
Проверка
Регрессионная проверка должна:
- выдать пару токенов;
- выполнить обновление после истечения access token;
- убедиться, что клиент сохранил новый
access_tokenи новыйrefresh_token; - повторить обновление с новой парой.
Отдельная проверка конфигурации должна запускать backend с отсутствующей JWT- переменной и ожидать явную ошибку старта. В исходной заметке автоматический тест для этого сценария не зафиксирован.
Общий вывод
Секреты и параметры безопасности не должны иметь тихих значений по умолчанию. Контракт обновления токенов нужно проверять как единый протокол: клиент должен сохранить все обновлённые значения, backend - выдать согласованную пару, а CI - передать именно те переменные, которые использует приложение.