sequenceDiagram
autonumber
actor App as APP (Мобильное приложение)
participant Nginx as Nginx Proxy
participant GW as GATEWAY (backend-api)
participant Auth as AUTH (auth-service)
participant Redis as REDIS (Token Blacklist)
participant DB as DB_AUTH (PostgreSQL)
App->>Nginx: Шаг 1: POST /api/v1/auth/refresh (refresh_token)
activate Nginx
Nginx->>GW: Шаг 2: POST /backend-api/v1/auth/refresh
activate GW
GW->>Auth: Шаг 3: gRPC: VerifyAndRotate(RefreshRequest)
activate Auth
Auth->>Redis: Шаг 4: Redis.EXISTS(revoked_refresh)
activate Redis
note over Auth, Redis: При падении Redis:<br/>Fail-Close -> Аварийный выход HTTP 503
Redis-->>Auth: Шаг 5: Токен НЕ найден в черном списке
deactivate Redis
Auth->>DB: Шаг 6: SQL SELECT is_revoked FROM user_sessions...
activate DB
DB-->>Auth: Токен валиден, срок не истек
deactivate DB
note over Auth: Шаг 7: Внутреннее действие:<br/>Атомарная деактивация старого<br/>и генерация нового токена
Auth->>DB: Шаг 7 (продолжение): SQL UPDATE и INSERT сессий
activate DB
DB-->>Auth: Сессия обновлена
deactivate DB
Auth-->>GW: Шаг 8: gRPC: RotateResponse
deactivate Auth
GW-->>App: Шаг 9: HTTP 200 OK (new access, new refresh)
deactivate GW
deactivate Nginx
note over App: Шаг 10: Внутренний метод<br/>SecureStorage.write(...) и разморозка очереди
Метод POST /api/v1/auth/refresh
Документация API: Фоновое обновление сессии (Refresh Token) с бесшовным перевыпуском Multi-Tenancy JWT Claims
- IAD-MIGRATION-120 Backlog — Создать таблицу auth_db.sessions.
- IAD-004 Ready for Development — Создать метод /api/v1/auth/refresh на API Gateway
- IAD-013 Ready for Development — создать метод ProcessUploadText.
- GW-102 Ready for Development — Подключение эндпоинта в шлюзе.
- INV-FRONTEND-2XX Refinement (Уточнение) — Экран управления B2B-интеграциями
- INV-FRONTEND-2XX Refinement (Уточнение) — Экран управления B2B-интеграциями
В открытом доступе представлена демонстрационная версия метода. В настоящей публичной документации отображены не все шаги, технические сценарии и приватные эндпоинты для системы цифровых симуляторов бизнес-процессов.
- Полная спецификация метода: Будет доступна только во внутреннем контуре разработки (Confluence / Swagger Enterprise).
1 Функциональное назначение
Метод предназначен для безопасного продолжения активной пользовательской сессии без повторного принудительного ввода логина и пароля на смартфоне.
В рамках микросервисной архитектуры этот эндпоинт решает инфраструктурные задачи:
- “Interceptor” т.н. “перехватчик”: Метод вызывается сетевым слоем приложения (APP) строго в фоновом режиме, когда шлюз возвращает ошибку
HTTP 401 Unauthorizedна любой транзакционный запрос. - Бесшовный перевыпуск контекста: Проверяет долгоживущий
Refresh Tokenпо базе сессий и генерирует новый короткоживущийAccess Token(JWT), сохраняя актуальные JWT Private Claimshome_group_id,account_typeиuser_id. Это гарантирует, что фоновые процессы сокетов и транзакции не прервутся для пользователя. - Механизм обновления токенов (Refresh Token Rotation): Для защиты от компрометации, при каждом вызове старый Refresh-токен отзывается, а клиенту выдается новая пара токенов, что предотвращает атаки типа Replay Attack.
2 Протокол взаимодействия (HTTP Контракт)
- Метод:
POST - Маршрут:
/api/v1/auth/refresh - Формат данных:
application/json
2.1 Спецификация заголовков (HTTP Headers)
| Заголовок | Обязательный | Описание | Пример значения |
|---|---|---|---|
Content-Type |
Да | Указывает на передачу строго типизированного JSON-пакета | application/json |
X-Request-ID |
Да | Сквозной ID запроса для трассировки фоновой ротации сессии | req-auth-ref-22aa |
2.2 Спецификация тела запроса (Request Body)
В соответствии с требованиями безопасности, Refresh-токен передается в теле JSON-запроса (или извлекается из защищенных HttpOnly Cookies в зависимости от конфигурации окружения).
| Поле | Тип | Обязательный | Описание | Пример значения |
|---|---|---|---|---|
refresh_token |
String | Да | Долгоживущий токен обновления, выданный при входе в систему | ref-token-xyz789... |
2.2.1 Пример сырого JSON-запроса (Payload):
{
"refresh_token": "ref-token-xyz789_v1_signature..."
}2.3 Спецификация успешного ответа (Response Body)
2.3.1 HTTP 200 OK
Возвращается при успешной валидации сессии. Выдается обновленный JWT-токен.
{
"status": "success",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3UrODgyMiIsImhvbWVfZ3JvdXBfaWQiOiJncm91cC03NzItYWxwaGEiLCJhY2NvdW50X3R5cCI6IkhPTUUiLCJleHAiOjE3ODMzMTMyMDB9.new_signature...",
"expires_in": 3600
}3 Диаграмма последовательности (Mermaid)
На диаграмме представлена логика работы “перехватчика” (Interceptor) при фоновом обновлении токенов. Сервис Auth проверяет refresh_token по базе активных сессий, выполняет обновление, отзывает старый ключ и выпускает новый JWT с сохранением JWT Private Claims.
4 Расшифровка шагов
| Шаг | Действие | Параметры / Запросы / DTO | Ошибки (Исключения / Статусы) |
|---|---|---|---|
Шаг 1 (App -> Nginx) |
При “протухании” Access-токена приложение фоново (Interceptor) отправляет запрос на ротацию сессии, передавая текущий Refresh-токен. |
HTTP POST /api/v1/auth/refreshPayload ( TokenRefreshRequestDTO):{ "refresh_token": "def456..." } |
DioException: send timeoutHTTP 400 Bad Request (пустой или невалидный по структуре токен ротации) |
Шаг 2 (Nginx -> Gateway) |
Прокси-сервер выполняет базовую маршрутизацию входящего запроса на шлюз. | HTTP POST /backend-api/v1/auth/refreshHeaders: X-Request-ID: "trace-auth-lifecycle-uuid" |
HTTP 502 Bad Gateway (контейнер backend-api недоступен)HTTP 504 Gateway Timeout |
Шаг 3 (Gateway -> Auth) |
API-шлюз обращается к контуру авторизации по gRPC-каналу для верификации и ротации токена. | Протокол: gRPC Метод: VerifyAndRotate(RefreshRequest)Параметры: refresh_token |
gRPC Status: UNAVAILABLE (сервис авторизации недоступен)gRPC Status: DEADLINE_EXCEEDED (таймаут обработки криптографии) |
Шаг 4 (Auth -> Redis) |
Сервис проверяет наличие хэша присланного Refresh-токена в черном списке отозванных токенов (Token Blacklist). | Redis Команда:EXISTS "revoked:refresh:hash_of_def456..." |
Fail-Close Аварийный выход: Redis.ConnectionError -> Перехват исключения на бэкенде и возврат HTTP 503 Service Unavailable |
Шаг 5 (Redis -> Auth) |
Redis возвращает статус проверки, подтверждая, что токен отсутствует в черном списке. | Ответ кэша: 0 (Токен НЕ найден в черном списке, проверка пройдена). |
Redis.TimeoutError: Command timed out |
Шаг 6 (Auth -> DB_Auth) |
Сервис запрашивает из PostgreSQL статус сессии для валидации срока её действия и флага отзыва. | SQL-запрос:SELECT is_revoked, expires_at FROM user_sessions WHERE refresh_token_hash = 'hash...' LIMIT 1; |
PostgreSQL Exception: ConnectionPoolTimeoutgRPC Status: UNAUTHENTICATED (сессия отозвана, просрочена или отсутствует в БД) |
Шаг 7 (Auth -> Auth) |
Внутреннее действие: сервис проверяет подпись токена в памяти, отзывает старый ключ и генерирует новую пару JWT со старыми Claims. | Внутренняя операция ротации токенов. Сдвиг временного окна сессии на новый TTL. JWT New Access Claims: { "sub": "usr-8822", "home_group_id": "group-772-alpha", "account_type": "HOME" } |
CryptoException: TokenGenerationFailed (сбой генерации) |
Шаг 7 (продолжение) (Auth -> DB_Auth) |
Сервис атомарно обновляет текущую сессию (помечая её старый токен отозванным) и выполняет новую запись сессии в БД. | SQL-запросы (в рамках одной транзакции):UPDATE user_sessions SET is_revoked = true WHERE refresh_token_hash = 'old_hash...';INSERT INTO user_sessions (user_id, refresh_token_hash, expires_at) VALUES ('usr-8822', 'new_hash...', '2026-08-27'); |
PostgreSQL Exception: UniqueViolationPostgreSQL Exception: TransactionAborted |
Шаг 8 (Auth -> Gateway) |
Модуль сессий возвращает сформированную новую пару токенов по gRPC-каналу обратно на API-шлюз. | Протокол: gRPC Ответ: RotateResponsePayload: access_token, refresh_token |
gRPC Status: INTERNAL (ошибка сборки структуры сообщения) |
Шаг 9 (Gateway -> App) |
Шлюз транслирует успешный HTTP-ответ 200 OK с новой парой токенов через Nginx на устройство. |
HTTP Статус на выходе Nginx: 200 OKResponse Body: { "status": "success", "token": "eyJhbGci...NEW_ACCESS", "refresh_token": "def456...NEW_REFRESH", "expires_in": 3600 } |
DioException: receive timeout (пара токенов обновлена в бэкенде, но клиент потерял TCP-сессию из-за обрыва связи) |
Шаг 10 (App -> App) |
Мобильное приложение перезаписывает токены в защищенном хранилище и возобновляет отправку ранее замороженных запросов. | Внутренний метод: SecureStorage.write(...)Запись в iOS Keychain или Android Keystore + разморозка очереди ( Interceptor Queue). |
SecureStorageException (ошибка стирания или записи ключей на смартфоне) |