← Все статьи

SiteGuard12 мин чтения

OAuth refresh token: как продлевать доступ интеграции без постоянного входа

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

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

Что продлевает refresh token и почему доступ не становится вечным

Access token приложение предъявляет при обращении к защищённому API. Refresh token нужен для получения нового доступа через сервер авторизации. Это разные роли: токен продления не следует подставлять вместо access token в запрос выгрузки клиентов. В RFC 6749 описано и другое существенное условие: сервер может выдать новый refresh token при обновлении; тогда клиент должен заменить сохранённое старое значение новым.

Для владельца сайта полезная модель выглядит так: пользователь разрешил конкретной интеграции работать с определёнными данными, а приложение поддерживает эту авторизацию, пока провайдер её допускает. Продление не расширяет права автоматически и не отменяет возможность отзыва. Удалённое приложение, изменившиеся полномочия или завершившийся срок действия могут потребовать нового подтверждения доступа.

Поэтому задача разработчика — поддерживать нормальный обмен и предусмотренно останавливать его, когда разрешение больше не действует. Цикл бесконечных попыток с прежними секретами не заменяет повторную авторизацию. В интерфейсе администратора должны различаться состояния «обмен работает», «временная ошибка обновления» и «нужно восстановить подключение».

Как устроено обновление токена Битрикс24

В документации Битрикс24 по продлению OAuth указаны сроки: access_token действует один час, refresh_token — 180 дней. Рекомендуемый рабочий путь: использовать сохранённый access token, при ответе expired_token с HTTP 401 получить новую пару, сохранить её и повторить исходный вызов. Обновлять токены перед каждым запросом либо по расписанию каждый час или сутки документация не рекомендует. Для редко используемого приложения отдельно предусмотрено поддержание авторизации до истечения refresh token.

Практически это означает два разных механизма: обновление по документированному признаку истечения доступа и контроль долго не используемого подключения. Во втором случае команда задаёт запас времени на ошибку сети и уведомление ответственного. Ожидание последней секунды срока создаёт ненужную зависимость от доступности сервера именно в этот момент.

Не переносите на Битрикс24 правила другого OAuth-провайдера. Выдача новой пары сама по себе не доказывает конкретную политику немедленного аннулирования старого refresh token или обнаружения повторного использования. Реализацию следует строить вокруг актуального договора API, не рассчитывая на недокументированное «окно», в котором старые значения якобы ещё работают.

Какие данные хранить вместе с парой токенов

Один текстовый файл с последним access token не описывает подключение целиком. Нужна запись, связывающая секреты с конкретным порталом, приложением, пользователем и средой. Иначе обновление тестового подключения может случайно повлиять на рабочую синхронизацию. В таблице ниже приведён проектный состав записи, а не обязательный формат Битрикс24.

ПолеДля чего нужно
Внутренний идентификатор подключенияИзолирует состояние, задачи и блокировку обновления
Идентификаторы портала и приложенияПомогают проверить, какому подключению принадлежит результат
Access token и refresh tokenХранятся как единая защищённая пара
Срок доступа и время полученияПозволяют объяснить состояние и обнаружить зависшее обновление
Версия пары и поколение авторизацииЗащищают от перезаписи более нового состояния старым ответом
Статус подключения и безопасный код ошибкиПомогают остановить задачи и сообщить причину без публикации секретов

Сроки сохраняйте в согласованном формате времени, например UTC, отдельно от локального представления для оператора. Записывайте, когда результат действительно сохранён, а не только когда начат запрос. При расследовании это помогает отличить свежую пару от старой записи, которую процесс ошибочно считает обновлённой.

Доступ к секретам нужен ограниченному серверному компоненту. Не включайте полные токены и client_secret в уведомления, трассировки, скриншоты и диагностические URL. Для поддержки достаточно идентификатора подключения, версии, времени, этапа и очищенного кода ошибки.

Как должен проходить обычный фоновый запрос

Централизуйте работу с авторизацией в одном слое интеграции. Если каждый обработчик самостоятельно решает, когда обновлять токен, одинаковая ошибка быстро превращается в десятки одновременных запросов. При этом отдельный слой не обязан быть отдельным сервисом: важны единые правила для всех процессов, которые используют подключение.

  1. Задача получает актуальную запись подключения и запоминает её версию.
  2. Клиент выполняет нужный метод API с access token.
  3. При документированном признаке истечения он обращается к общему механизму продления.
  4. Механизм повторно читает состояние, координирует обновление и сохраняет результат.
  5. Задача получает уже сохранённые учётные данные и продолжает работу по правилам повторов своего метода.

Важна граница между ошибкой доступа и неизвестным результатом бизнес-запроса. Если соединение оборвалось после отправки операции создания записи, отсутствие ответа не доказывает, что операция не выполнена. Обновление токена не даёт основания безусловно повторять создание. Для такой операции отдельно нужны идентификатор, проверка результата и предусмотренный API механизм защиты от дублей.

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

Почему новую пару нужно сохранять атомарно

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

Проектируйте сохранение как одну операцию над согласованным состоянием: оба токена, срок доступа, версия и время обновления переходят вместе. В базе данных это обычно транзакция с условием на ожидаемую версию. Другие процессы должны видеть либо предыдущую полную пару, либо новую полную пару. Частично заполненное состояние не должно считаться успешным подключением.

Успешный HTTP-ответ сервера авторизации ещё не означает успешного обновления интеграции. Подтверждать его рабочим задачам можно после надёжной фиксации. Если хранилище временно недоступно, считайте обновление неподтверждённым и приостановите потребителей, которым нужна новая пара. Не выводите секретный ответ в обычный лог в надежде восстановить его вручную.

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

Если применяется SDK, выясните, кто именно отвечает за долговременную запись обновлённых значений. Изменение токена в памяти текущего объекта не помогает следующему процессу после перезапуска. Проверяйте весь путь: ответ сервера, событие обновления в библиотеке, обработчик сохранения, подтверждение записи и чтение новым экземпляром клиента. Ответственность за этот участок должна быть явно закреплена в проекте.

Как исключить параллельные обновления одной авторизации

Два воркера могут одновременно получить отказ для одной версии access token. Если оба сразу отправят refresh token, дальнейший результат будет зависеть от правил провайдера и порядка ответов. Даже когда обе попытки завершатся успешно, одна из них может сохранить уже неактуальную пару.

Практическое решение — координация по идентификатору подключения: один исполнитель обновляет доступ, остальные ожидают результат или откладывают задачи. Блокировка только внутри одного процесса недостаточна, если приложение работает на нескольких серверах. Все писатели этой записи должны участвовать в одном механизме согласования.

После получения права на обновление обязательно перечитайте запись. Возможно, пока процесс ждал, другой исполнитель уже сохранил следующую версию. Тогда новый refresh-запрос не нужен: задача использует актуальное состояние. Этот повторный просмотр предотвращает последовательный «паровоз» обновлений, когда очередь ожидавших процессов по одному продлевает только что выданный доступ.

Учитывайте падение владельца блокировки и слишком долгий сетевой вызов. Истечение срока блокировки не отменяет запрос, который уже ушёл на удалённый сервер. Поэтому время владения, продление блокировки, ограничение длительности запроса и условие записи результата необходимо проектировать вместе. Одного признака «сейчас никто не держит замок» недостаточно для доказательства отсутствия старой операции.

Как не дать старому ответу затереть новую авторизацию

Версия пары защищает от запоздавших ответов внутри одного подключения. Исполнитель начинает обновление версии 7 и имеет право записать результат только при ожидаемом состоянии. Если в хранилище уже версия 8, безусловное присваивание запрещено. Такой отказ записи нужно разбирать как конфликт, а не незаметно повторять поверх новых данных.

Отдельное поколение авторизации требуется при повторном подключении пользователем. Представьте: старый refresh-запрос задержался, администратор прошёл вход заново, приложение сохранило новую авторизацию, затем пришёл старый ответ. Даже совпадение локального счётчика версии не должно позволять вернуть прежние полномочия. Поэтому результат связывают и с поколением, и с исходной версией записи.

Условная запись решает локальную проблему перезаписи, но не отменяет последствия двух уже отправленных запросов на сервере провайдера. Основная защита — не допускать конкурентного продления; проверка версии служит дополнительным барьером. Если конкуренция всё-таки произошла, нельзя автоматически объявлять любую оставшуюся пару рабочей без проверки принятого состояния.

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

Почему timeout обновления не равен invalid_grant

При timeout клиент не получил завершённый ответ. Сервер мог не принять запрос, мог ещё обрабатывать его, а мог уже выпустить новые токены, которые не дошли до приложения. Поэтому нельзя сразу удалить сохранённую пару, объявить авторизацию отозванной или без ограничений повторять прежний refresh token.

OAuth Security BCP, RFC 9700 описывает ротацию refresh token с обнаружением повторного использования. В такой схеме старое значение после обмена аннулируется, а его повторное предъявление может привести к отзыву активного токена. Это объясняет риск слепых повторов, но не является утверждением, что Битрикс24 использует именно такую политику.

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

Обычный технический сбой не должен мгновенно отправлять всем пользователям просьбу войти заново. Но и скрывать остановку фонового обмена нельзя. Ответственному нужно показать неопределённый статус, затронутые задачи и следующий шаг, не подменяя неизвестный результат уверенным диагнозом.

Как разделить ошибки параметров, отзыва и прав

Разбирайте ответ сервера авторизации отдельно от ответа прикладного REST-метода. В справочнике ошибок Битрикс24 invalid_client связан с данными приложения, invalid_grant — с некорректными авторизационными данными, а ошибки scope — с запрошенными правами. При истёкшем refresh token документация направляет к повторной полной авторизации. Один лишь текст «токен истёк» в интерфейсе скрывает эти различия.

НаблюдениеЧто выяснитьСледующее действие команды
Отказ проверки приложенияВерны ли настройки и выбранное окружениеИсправить конфигурацию, сохранив диагностические сведения
Отказ продления grantНе устарела ли локальная запись, не отозван ли доступПроверить состояние; при необходимости запросить новый вход
Недостаточные праваКакая операция требует отсутствующего разрешенияСогласовать права или ограничить сценарий
Сетевой сбой без полного ответаИзвестен ли итог попытки обновленияПрименить процедуру неопределённого результата

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

Как повторно подключить интеграцию и продолжить очередь

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

Затем подтвердите необходимые права безопасным вызовом, не создающим реальные заказы или сообщения. Успех получения токенов ещё не доказывает, что возобновившаяся интеграция может выполнить все нужные действия. Пользователь мог выбрать другой аккаунт или выдать меньше разрешений, чем требует рабочий сценарий.

Очередь продолжайте с сохранённой контрольной точки. Не запускайте всю историю заново только потому, что поменялась авторизация. У каждой задачи должны сохраняться собственные признаки выполнения и сведения о неопределённом результате. Доступ и бизнес-прогресс — разные состояния: восстановление первого не обнуляет второй.

Возобновление делайте управляемым: сначала подтвердите корректность одного безопасного шага, затем снимайте паузу. Если накопилось много задач, учитывайте производительность обработчиков и ограничения API. Период простоя интеграции не становится разрешением резко увеличить частоту запросов.

Учебный пример: два воркера и одна новая пара

Рассмотрим условную интеграцию. В хранилище находится поколение авторизации A, версия пары 7. Два обработчика синхронизации почти одновременно обнаруживают документированное истечение доступа. Все обозначения ниже вымышлены и не являются токенами.

Время UTCСобытиеСостояние
10:00:00.000Воркеры W1 и W2 получают отказ для версии 7Оба обращаются к общей процедуре
10:00:00.050W1 получает право обновленияW2 ожидает
10:00:00.300W1 получает новую паруРабочие задачи ещё не используют ответ
10:00:00.340Пара атомарно сохранена как версия 8Обновление подтверждено
10:00:00.360W2 перечитывает записьИспользует версию 8 без второго refresh-запроса

В этом сценарии отправлен один запрос продления, хотя истечение заметили два обработчика. Если перед последней строкой пользователь заново подключил приложение и появилось поколение B, старый исполнитель не должен записывать данные поколения A. Такой вариант проверяют отдельно: удачный основной сценарий не доказывает защиты от позднего ответа.

Что проверить перед запуском и что наблюдать дальше

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

  • Истёкший access token приводит к одному согласованному обновлению и сохранению полной пары.
  • Несколько процессов не создают независимые цепочки refresh-запросов.
  • Сбой записи не оставляет смесь старого и нового состояния.
  • Поздний ответ не перезаписывает следующую версию или новую авторизацию.
  • Timeout, отказ grant и ошибка конфигурации получают разные статусы.
  • После повторного входа очередь продолжается без обнуления прогресса.
  • Логи и уведомления не содержат секретов; долго не используемое подключение не теряется незаметно.

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

Добавьте проверку после штатного перезапуска приложения: оно должно продолжить работу с сохранённым состоянием, не требуя ручного копирования секретов. При замене клиента или переносе воркеров повторите этот сценарий. Успешная работа старого процесса с токеном в памяти может скрывать неисправное хранилище до ближайшего релиза.

Дополните внутренний контроль интеграции внешним наблюдением за HTTP-доступностью сайта через SiteGuard. Так команда получит отдельный сигнал о доступности веб-узла, а состояние OAuth и корректность фонового обмена останутся предметом её собственных проверок.