sequenceDiagram
autonumber
actor App as APP (Mobile 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: Step 1: POST /api/v1/auth/refresh (refresh_token)
activate Nginx
Nginx->>GW: Step 2: POST /backend-api/v1/auth/refresh
activate GW
GW->>Auth: Step 3: gRPC: VerifyAndRotate(RefreshRequest)
activate Auth
Auth->>Redis: Step 4: Redis.EXISTS(revoked_refresh)
activate Redis
note over Auth, Redis: If Redis Fails:<br/>Fail-Close -> Emergency Exit HTTP 503
Redis-->>Auth: Step 5: Token NOT found in the blacklist
deactivate Redis
Auth->>DB: Step 6: SQL SELECT is_revoked FROM user_sessions...
activate DB
DB-->>Auth: Token is valid and not expired
deactivate DB
note over Auth: Step 7: Internal action:<br/>Atomic deactivation of old token<br/>and new token generation
Auth->>DB: Step 7 (continued): SQL UPDATE and INSERT sessions
activate DB
DB-->>Auth: Session updated
deactivate DB
Auth-->>GW: Step 8: gRPC: RotateResponse
deactivate Auth
GW-->>App: Step 9: HTTP 200 OK (new access, new refresh)
deactivate GW
deactivate Nginx
note over App: Step 10: Internal method<br/>SecureStorage.write(...) and unfreeze queue
Метод 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).
Функциональное назначение
This documentation section is currently under development and may contain incomplete data. Some technical descriptions, parameters, and system operation scenarios for the digital business process simulator are subject to change.
- Stable documentation version: Will be published upon final completion and validation of the method code.
This method is designed to securely extend an active user session without forcing the user to re-enter their username and password on the smartphone.
Under the microservice architecture, this endpoint addresses key infrastructural tasks:
- “Interceptor” Mechanism: The method is triggered by the application’s (APP) network layer in the background whenever the gateway returns an
HTTP 401 Unauthorizederror for any transactional request. - Seamless Context Re-issue: It validates the long-lived
Refresh Tokenagainst the session database and generates a new short-livedAccess Token(JWT), preserving the current JWT Private Claims:home_group_id,account_type, anduser_id. This ensures that background socket processes and transactions remain completely uninterrupted for the user. - Refresh Token Rotation (RTR): To protect against token compromise, the old Refresh Token is revoked upon every invocation, and a brand-new token pair is issued to the client, preventing Replay Attacks.
Interaction Protocol (HTTP Contract)
- Method:
POST - Route:
/api/v1/auth/refresh - Data Format:
application/json
Header Specification (HTTP Headers)
| Header | Required | Description | Example Value |
|---|---|---|---|
Content-Type |
Yes | Specifies the transmission of a strictly typed JSON payload | application/json |
X-Request-ID |
Yes | End-to-end request ID for background session rotation tracing | req-auth-ref-22aa |
Request Body Specification (Request Body)
In compliance with security requirements, the Refresh Token is passed in the JSON request body (or extracted from secure HttpOnly Cookies depending on the environment configuration).
| Field | Type | Required | Description | Example Value |
|---|---|---|---|---|
refresh_token |
String | Yes | The long-lived refresh token issued during login | ref-token-xyz789... |
Request JSON Example (Payload):
{
"refresh_token": "ref-token-xyz789_v1_signature..."
}Success Response Specification (Response Body)
HTTP 200 OK
Returned upon successful session validation. A renewed JWT token is issued.
{
"status": "success",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3UrODgyMiIsImhvbWVfZ3JvdXBfaWQiOiJncm91cC03NzItYWxwaGEiLCJhY2NvdW50X3R5cCI6IkhPTUUiLCJleHAiOjE3ODMzMTMyMDB9.new_signature...",
"expires_in": 3600
}Метод предназначен для безопасного продолжения активной пользовательской сессии без повторного принудительного ввода логина и пароля на смартфоне.
В рамках микросервисной архитектуры этот эндпоинт решает инфраструктурные задачи:
- “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.
Протокол взаимодействия (HTTP Контракт)
- Метод:
POST - Маршрут:
/api/v1/auth/refresh - Формат данных:
application/json
Спецификация заголовков (HTTP Headers)
| Заголовок | Обязательный | Описание | Пример значения |
|---|---|---|---|
Content-Type |
Да | Указывает на передачу строго типизированного JSON-пакета | application/json |
X-Request-ID |
Да | Сквозной ID запроса для трассировки фоновой ротации сессии | req-auth-ref-22aa |
Спецификация тела запроса (Request Body)
В соответствии с требованиями безопасности, Refresh-токен передается в теле JSON-запроса (или извлекается из защищенных HttpOnly Cookies в зависимости от конфигурации окружения).
| Поле | Тип | Обязательный | Описание | Пример значения |
|---|---|---|---|---|
refresh_token |
String | Да | Долгоживущий токен обновления, выданный при входе в систему | ref-token-xyz789... |
Пример сырого JSON-запроса (Payload):
{
"refresh_token": "ref-token-xyz789_v1_signature..."
}Спецификация успешного ответа (Response Body)
HTTP 200 OK
Возвращается при успешной валидации сессии. Выдается обновленный JWT-токен.
{
"status": "success",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3UrODgyMiIsImhvbWVfZ3JvdXBfaWQiOiJncm91cC03NzItYWxwaGEiLCJhY2NvdW50X3R5cCI6IkhPTUUiLCJleHAiOjE3ODMzMTMyMDB9.new_signature...",
"expires_in": 3600
}Диаграмма последовательности (Mermaid)
The diagram illustrates the logic of the “Interceptor” during the background token rotation process. The Auth service checks the refresh_token against the active sessions database, performs the update, revokes the old key, and issues a new JWT while preserving the JWT Private Claims.
На диаграмме представлена логика работы “перехватчика” (Interceptor) при фоновом обновлении токенов. Сервис Auth проверяет refresh_token по базе активных сессий, выполняет обновление, отзывает старый ключ и выпускает новый JWT с сохранением JWT Private Claims.
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(...) и разморозка очереди
Расшифровка шагов
| Step | Action | Parameters / Requests / DTO | Errors (Exceptions / Statuses) |
|---|---|---|---|
Step 1 (App -> Nginx) |
When the Access Token expires, the app background interceptor sends a session rotation request, passing the current Refresh Token. | HTTP POST /api/v1/auth/refreshPayload ( TokenRefreshRequestDTO):{ "refresh_token": "def456..." } |
HTTP 400 Bad Request (empty or structurally malformed rotation token) |
Step 2 (Nginx -> Gateway) |
The proxy server performs basic routing of the incoming request to the API gateway. | HTTP POST /backend-api/v1/auth/refreshHeaders: X-Request-ID: "trace-auth-lifecycle-uuid" |
No business errors |
Step 3 (Gateway -> Auth) |
The API gateway contacts the authentication контур over the gRPC channel for token verification and rotation. | Protocol: gRPC Method: VerifyAndRotate(RefreshRequest)Parameters: refresh_token |
No business errors |
Step 4 (Auth -> Redis) |
The service checks whether the hash of the provided Refresh Token is in the Token Blacklist. | Redis Command:EXISTS "revoked:refresh:hash_of_def456..." |
Fail-Close Emergency Exit: Returns a business status HTTP 503 Service Unavailable to the client when session security cannot be guaranteed |
Step 5 (Redis -> Auth) |
Redis returns the validation status, confirming that the token is not present in the blacklist. | Cache response: 0 (Token NOT found in the blacklist, verification passed). |
No business errors |
Step 6 (Auth -> DB_Auth) |
The service requests the session status from PostgreSQL to validate its expiration date and revocation flag. | SQL Query:SELECT is_revoked, expires_at FROM user_sessions WHERE refresh_token_hash = 'hash...' LIMIT 1; |
gRPC Status: UNAUTHENTICATED (session is revoked, expired, or missing in the DB) |
Step 7 (Auth -> Auth) |
Internal action: the service verifies the token signature in memory, revokes the old key, and generates a new JWT pair preserving the old claims. | Internal token rotation operation. Shifting the session time window to a new TTL. JWT New Access Claims: { "sub": "usr-8822", "home_group_id": "group-772-alpha", "account_type": "HOME" } |
No business errors |
Step 7 Continued (Auth -> DB_Auth) |
The service atomically updates the current session (marking its old token as revoked) and writes the new session record to the DB. | SQL Queries (within a single transaction):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'); |
No business errors |
Step 8 (Auth -> Gateway) |
The session module returns the generated new token pair over the gRPC channel back to the API gateway. | Protocol: gRPC Response: RotateResponsePayload: access_token, refresh_token |
No business errors |
Step 9 (Gateway -> App) |
The gateway relays the successful 200 OK HTTP response containing the new token pair through Nginx back to the device. |
HTTP Status at Nginx exit: 200 OKResponse Body: { "status": "success", "token": "eyJhbGci...NEW_ACCESS", "refresh_token": "def456...NEW_REFRESH", "expires_in": 3600 } |
No business errors |
Step 10 (App -> App) |
The mobile app overwrites the tokens in the secure storage and resumes sending previously frozen network requests. | Internal method: SecureStorage.write(...)Saves tokens to iOS Keychain or Android Keystore + unfreezes the Interceptor Queue. |
No business errors |
| Шаг | Действие | Параметры / Запросы / DTO | Ошибки (Исключения / Статусы) |
|---|---|---|---|
Шаг 1 (App -> Nginx) |
При истечении времени жизни Access-токена приложение в фоновом режиме (Interceptor) отправляет запрос на ротацию сессии, передавая текущий Refresh-токен. |
HTTP POST /api/v1/auth/refreshPayload ( TokenRefreshRequestDTO):{ "refresh_token": "def456..." } |
HTTP 400 Bad Request (пустой или структурно невалидный токен ротации в теле запроса) |
Шаг 2 (Nginx -> Gateway) |
Прокси-сервер выполняет базовую маршрутизацию входящего запроса на шлюз API. | HTTP POST /backend-api/v1/auth/refreshHeaders: X-Request-ID: "trace-auth-lifecycle-uuid" |
Бизнес-ошибки отсутствуют |
Шаг 3 (Gateway -> Auth) |
API-шлюз обращается к контуру авторизации по внутреннему gRPC-каналу для верификации и перевыпуска пары токенов. | Протокол: gRPC Метод: VerifyAndRotate(RefreshRequest)Параметры: refresh_token |
Бизнес-ошибки отсутствуют |
Шаг 4 (Auth -> Redis) |
Сервис проверяет наличие хэша присланного Refresh-токена в черном списке отозванных токенов (Token Blacklist) для предотвращения атак повторения. | Redis Команда:EXISTS "revoked:refresh:hash_of_def456..." |
Fail-Close Аварийный выход: Возврат бизнес-статуса HTTP 503 Service Unavailable при невозможности кэша гарантировать безопасность проверки |
Шаг 5 (Redis -> Auth) |
Redis возвращает статус проверки, подтверждая, что токен отсутствует в черном списке. | Ответ кэша: 0 (Токен НЕ найден в черном списке, проверка безопасности пройдена успешно). |
Бизнес-ошибки отсутствуют |
Шаг 6 (Auth -> DB_Auth) |
Сервис запрашивает из PostgreSQL статус текущей сессии для валидации срока её действия и флага принудительного отзыва. | SQL-запрос:SELECT is_revoked, expires_at FROM user_sessions WHERE refresh_token_hash = 'hash...' LIMIT 1; |
gRPC Status: UNAUTHENTICATED (сессия уже была отозвана ранее, срок её действия полностью истек или запись отсутствует в БД) |
Шаг 7 (Auth -> Auth) |
Внутреннее действие: сервис проверяет криптографическую подпись токена, отзывает старый ключ и генерирует новую пару JWT с сохранением старых Claims. | Внутренняя операция ротации токенов. Сдвиг временного окна сессии на новый TTL. JWT New Access Claims: { "sub": "usr-8822", "home_group_id": "group-772-alpha", "account_type": "HOME" } |
Бизнес-ошибки отсутствуют |
Шаг 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'); |
Бизнес-ошибки отсутствуют |
Шаг 8 (Auth -> Gateway) |
Модуль сессий возвращает сформированную новую пару токенов по gRPC-каналу обратно на API-шлюз. | Протокол: gRPC Ответ: RotateResponsePayload: access_token, refresh_token |
Бизнес-ошибки отсутствуют |
Шаг 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 } |
Бизнес-ошибки отсутствуют |
Шаг 10 (App -> App) |
Мобильное приложение перезаписывает токены в защищенном хранилище смартфона и возобновляет отправку ранее замороженных запросов. | Внутренний метод: SecureStorage.write(...)Запись в iOS Keychain или Android Keystore + разморозка очереди перехватчика ( Interceptor Queue). |
Бизнес-ошибки отсутствуют |
Protobuf Контракт: VerifyAndRotate
Данный gRPC-контракт описывает процедуру фоновой ротации и верификации сессии (Refresh Token Rotation).
syntax = "proto3";
package auth.v1;
option go_package = "auth/v1;authv1";
// Сервис управления сессиями и авторизацией
service AuthService {
// Фоновое обновление сессии и ротация токенов (Refresh Token Rotation)
rpc VerifyAndRotate (RefreshRequest) returns (RotateResponse);
}
// Запрос на ротацию сессии (Шаг 3 диаграммы)
message RefreshRequest {
// Текущий токен обновления (Refresh Token), полученный от клиента
string refresh_token = 1;
}
// Ответ с новой парой токенов (Шаг 8 диаграммы)
message RotateResponse {
// Новый криптографически подписанный токен доступа (с сохраненными Claims)
string access_token = 1;
// Новый токен обновления (старый аннулируется)
string refresh_token = 2;
// Время жизни нового access-токена в секундах
int32 expires_in = 3;
}