Метод POST /api/v1/auth/refresh

Документация API: Фоновое обновление сессии (Refresh Token) с бесшовным перевыпуском Multi-Tenancy JWT Claims

Author

Application & Simulation Services Framework Documentation

Published

July 2, 2026

WarningОграничение публичной документации

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

  • Полная спецификация метода: Будет доступна только во внутреннем контуре разработки (Confluence / Swagger Enterprise).

Функциональное назначение

ImportantDocumentation Under Development

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:

  1. “Interceptor” Mechanism: The method is triggered by the application’s (APP) network layer in the background whenever the gateway returns an HTTP 401 Unauthorized error for any transactional request.
  2. Seamless Context Re-issue: It validates the long-lived Refresh Token against the session database and generates a new short-lived Access Token (JWT), preserving the current JWT Private Claims: home_group_id, account_type, and user_id. This ensures that background socket processes and transactions remain completely uninterrupted for the user.
  3. 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
}

Метод предназначен для безопасного продолжения активной пользовательской сессии без повторного принудительного ввода логина и пароля на смартфоне.

В рамках микросервисной архитектуры этот эндпоинт решает инфраструктурные задачи:

  1. “Interceptor” т.н. “перехватчик”: Метод вызывается сетевым слоем приложения (APP) в фоновом режиме, когда шлюз возвращает ошибку HTTP 401 Unauthorized на любой транзакционный запрос.
  2. Бесшовный перевыпуск контекста: Проверяет долгоживущий Refresh Token по базе сессий и генерирует новый короткоживущий Access Token (JWT), сохраняя актуальные JWT Private Claims home_group_id, account_type и user_id. Это гарантирует, что фоновые процессы сокетов и транзакции не прервутся для пользователя.
  3. Механизм обновления токенов (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.

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

Token Rotation Process (Refresh)

На диаграмме представлена логика работы “перехватчика” (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(...) и разморозка очереди

Процесс ротации токенов (Refresh)

Расшифровка шагов

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/refresh
Payload (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/refresh
Headers:
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: RotateResponse
Payload: 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 OK
Response 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/refresh
Payload (TokenRefreshRequestDTO):
{ "refresh_token": "def456..." }
HTTP 400 Bad Request (пустой или структурно невалидный токен ротации в теле запроса)
Шаг 2 (Nginx -> Gateway) Прокси-сервер выполняет базовую маршрутизацию входящего запроса на шлюз API. HTTP POST /backend-api/v1/auth/refresh
Headers:
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
Ответ: RotateResponse
Payload: access_token, refresh_token
Бизнес-ошибки отсутствуют
Шаг 9 (Gateway -> App) Шлюз транслирует успешный HTTP-ответ 200 OK с новой парой токенов через Nginx на устройство клиента. HTTP Статус на выходе Nginx: 200 OK
Response 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;
}