Files
BitrixDealsBot/docs/adr/003-oauth-credential-lifecycle.md

54 lines
4.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-003: защита и обновление OAuth-токенов
**Статус:** Принято
**Дата:** 2026-07-23
## Контекст
Для выполнения REST-запросов приложение хранит `access_token` и `refresh_token`.
Битрикс24 возвращает новую пару токенов при каждом обновлении, поэтому
одновременное использование одного refresh-токена несколькими воркерами может
привести к потере актуальной пары.
## Решение
До передачи в PostgreSQL `access_token` и `refresh_token` шифруются алгоритмом
Fernet. Общий `TOKEN_ENCRYPTION_KEY` передаётся контейнерам `site` и `bot` через
переменные окружения, но не записывается в базу. Бот расшифровывает access-токен
непосредственно перед REST-запросом и не включает OAuth-параметры в тексты
ошибок.
Принятые меры защиты сведены в таблицу.
| Риск | Реализованная мера | Остаточный контроль |
|---------------------------------|--------------------------------------------|--------------------------------------|
| Утечка одноразовой ссылки из БД | Хранение SHA-256-хеша | Короткий TTL и однократное погашение |
| Чтение OAuth-токенов из БД | Fernet-шифрование до INSERT/UPDATE | Секретный ключ вне БД |
| Подмена пользователя | member_id/user_id из OAuth + user.current | Проверка HTTPS endpoint |
| Гонка refresh token | Версия и аренда refresh_locked_until | Повторное чтение до версии N+1 |
| Избыточные права приложений | Разные роли и EXECUTE только на функции | REVOKE для PUBLIC |
| Долгая транзакция | Сетевые запросы выполняются вне транзакции | Короткие контексты Psycopg |
*Таблица ADR-003/1. Риски и меры защиты от них*
При получении `expired_token`, `invalid_token` или `no_auth_found` клиент
пытается обновить пару токенов. Поле `version` реализует оптимистическую
проверку, а `refresh_locked_until` — короткую аренду продолжительностью 30
секунд. Это предотвращает одновременное использование одного refresh-токена
несколькими воркерами.
После успешного обновления токенов воркер освобождает аренду. Если она занята,
другой воркер ожидает обновления, после чего повторяет обращение к API с новой
парой токенов.
![Диаграмма последовательности обновления OAuth-токена](assets/report/oauth-refresh-sequence.png)
*Рисунок ADR-003/1. Диаграмма последовательности обновления OAuth-токена*
## Последствия
Сетевой запрос к OAuth выполняется вне транзакции PostgreSQL. Версия и аренда
координируют обновление между воркерами, а повторное чтение позволяет продолжить
работу с версией `N+1`. Дальнейшее развитие механизма защиты предусматривает
ротацию ключей шифрования.