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/logout (Bearer Access / Body Refresh)
activate Nginx
Nginx->>GW: Шаг 2: POST /backend-api/v1/auth/logout
activate GW
GW->>Auth: Шаг 3: gRPC: LogoutUser(LogoutRequest)
activate Auth
Auth->>Redis: Шаг 4: Redis.SET(blacklist:access, ex=TTL)
activate Redis
note over Auth, Redis: При падении Redis:<br/>Fail-Close -> Аварийный выход HTTP 503
Redis-->>Auth: Токен успешно заблокирован в кэше
deactivate Redis
Auth->>DB: Шаг 5: SQL UPDATE user_sessions SET is_revoked = true...
activate DB
DB-->>Auth: Статус сессии обновлен в БД
deactivate DB
Auth-->>GW: Шаг 6: gRPC: LogoutResponse
deactivate Auth
GW-->>App: Шаг 7: HTTP 200 OK (status: success)
deactivate GW
deactivate Nginx
note over App: Шаг 8: Внутренний метод<br/>SecureStorage.deleteAll() и редирект
Метод POST /api/v1/auth/logout
Документация API: Деактивация сессии пользователя (Logout) с каскадной инвалидацией WebSocket-дескрипторов
- IAD-MIGRATION-116 Backlog — Краткое Описание задачи 1.
- IAD-MIGRATION-117 Refinement (Уточнение) — Краткое Описание задачи 2.
- GW-2 Ready for Development — Подключение эндпоинта в шлюзе.
- AID-012 Ready for Development — создать метож ProcessVoiceStream.
- AID-013 Ready for Development — создать метож ProcessUploadText.
- INV-FRONTEND-222 Refinement (Уточнение) — Экран управления B2B-интеграциями
- INV-FRONTEND-223 Refinement (Уточнение) — Экран управления B2B-интеграциями
1 Функциональное назначение
Метод предназначен для корректного и безопасного завершения текущей пользовательской сессии в экосистеме .
В рамках новой распределенной архитектуры метод POST /logout решает три ключевые задачи:
- Аннулирование долгоживущей сессии (Revocation): Переводит флаг
is_revokedцелевогоrefresh_tokenв состояниеtrueв таблицеuser_sessions, полностью блокируя возможность фонового продления сессии черезDio Interceptor. - Очистка ресурсов WebSocket-менеджера: Отправляет внутренний асинхронный сигнал в оперативную память шлюза
FastAPI, чтобы принудительно закрыть текущий активный WSS-стрим (/ws/push-stream/{id}) именно для этого девайса, предотвращая утечки памяти и отправку системных пушей на отключенное устройство. - Безопасный сброс стейта UI: Служит триггером для мобильного приложения Flutter для полной очистки локальных хранилищ
Flutter Secure Storageи переключения интерфейса на стартовый экран авторизации.
2 Протокол взаимодействия (HTTP Контракт)
- Метод:
POST - Маршрут:
/api/v1/auth/logout - Формат данных:
application/json
2.1 Спецификация заголовков (HTTP Headers)
| Заголовок | Обязательный | Описание | Пример значения |
|---|---|---|---|
Content-Type |
Да | Указывает на передачу JSON-пакета | application/json |
Authorization |
Да | Токен доступа (Access Token). Шлюз вычитывает user_id и home_group_id. |
Bearer eyJhbGciOiJIUzI1Ni... |
X-Request-ID |
Да | Сквозной ID запроса для трассировки сессии выхода из системы | req-auth-out-77aa |
2.2 Спецификация тела запроса (Request Body)
В теле запроса клиент явно передает текущий валидный refresh_token, который подлежит уничтожению в базе данных.
| Поле | Тип | Обязательный | Описание | Пример значения |
|---|---|---|---|---|
refresh_token |
String | Да | Токен обновления, который необходимо аннулировать в СУБД | ref-token-xyz789... |
2.2.1 Пример сырого JSON-запроса (Payload):
{
"refresh_token": "ref-token-xyz789_v1_signature..."
}3 Схема обработки запроса пользователя (Mermaid)
На диаграмме представлена логика безопасного выхода из системы (POST /logout). Сервис Auth блокирует refresh_token в PostgreSQL, после чего шлюз FastAPI обращается к своему пулу активных соединений и принудительно гасит WebSocket-стрим этого смартфона, освобождая оперативную память сервера.
4 Расшифровка шагов
| Шаг | Действие | Параметры | Ошибки (Исключения / Статусы) |
|---|---|---|---|
Шаг 1 (APP -> NGINX) |
Пользователь нажимает «Выход». Приложение отправляет запрос, прикрепляя текущий Access Token в заголовок, а Refresh Token в тело. |
HTTP POST /api/v1/auth/logoutHeaders: Bearer (Access)Body: {"refresh_token": "..."} |
DioException: no internet connection |
Шаг 2 (NGINX -> GATEWAY) |
Nginx пересылает запрос деактивации на API Gateway. |
HTTP POST /backend-api/v1/auth/logout |
HTTP 502 Bad Gateway |
Шаг 3 (GATEWAY -> AUTH) |
API Gateway проверяет метаданные и отправляет gRPC-команду на полное аннулирование сессии. | gRPC: LogoutUser(LogoutRequest) |
HTTP 422 Unprocessable Entity |
Шаг 4 (AUTH -> REDIS) |
Сервис мгновенно заносит Access Token в Redis Blacklist с временем жизни (TTL), равным остатку его действия. |
Вызов: Redis.SET(f"blacklist:{access_jti}", ..., ex=TTL) |
Redis: ConnectionRefusedErrorgRPC: UNAVAILABLE \(\rightarrow\) Fail-Close! HTTP 503 |
Шаг 5 (AUTH -> DB_AUTH) |
Сервис обновляет статус долгоживущей сессии в PostgreSQL, переводя признак is_revoked в true. |
SQL UPDATE user_sessions SET is_revoked = true WHERE refresh_token_jti = $1 |
PostgreSQL: connection pool timeout |
Шаг 6 (AUTH -> GATEWAY) |
Контур авторизации подтверждает успешный отзыв всех ключей доступа и сессий. | gRPC: LogoutResponse |
gRPC: INTERNAL |
Шаг 7 (GATEWAY -> APP) |
API Gateway возвращает статус успешного выполнения операции на мобильный клиент. | HTTP 200 OKBody: {"status": "success"} |
HTTP 500 Internal Server Error |
Шаг 8 (APP -> APP) |
Мобильное приложение полностью очищает Secure Storage от токенов и принудительно перенаправляет пользователя на экран авторизации. |
Вызов: SecureStorage.deleteAll() |
SecureStorageException |
5 Спецификация ответов сервера (Response Body) и ошибок
5.1 1. Успешный ответ (Success Response)
5.1.1 HTTP 200 OK (Ответ на Шаге 8)
Возвращается мобильному приложению после успешного коммита транзакции деактивации. В теле ответа фиксируется успешное уничтожение сессии.
- Заголовки ответа (Response Headers):
Content-Type: application/json
- Тело ответа (Response Body):
{
"status": "success",
"data": {
"message": "SESSION_TERMINATED",
"details": "Refresh token successfully revoked. Active WebSocket connection terminated clean.",
"timestamp": "2026-07-02T02:20:00Z"
}
}5.2 2. Вилки исключений и обработка ошибок
5.2.1 Ошибка: Токен не найден или уже аннулирован (HTTP 404 Not Found)
Выбрасывается, если переданный в JSON-теле refresh_token отсутствует в таблице user_sessions, либо если его флаг is_revoked уже равен true (например, метод logout был вызван повторно).
- Заголовки ответа (Response Headers):
Content-Type: application/json
- Тело ответа (Response Body):
{
"error_code": "ERR-LOGOUT-TARGET-NOT-FOUND",
"message": "Указанная сессия обновления не найдена или была аннулирована ранее.",
"details": {
"action": "Proceed with local state clearance in Flutter securely as session is already dead on server."
}
}5.2.2 Ошибка валидации структуры (HTTP 422 Unprocessable Entity)
Выбрасывается бэкенд-шлюзом FastAPI при передаче пустого поля токена.
{
"error_code": "ERR-VALIDATION-FAILED",
"message": "Передан некорректный или пустой токен для аннулирования сессии.",
"details": [
{
"loc": ["body", "refresh_token"],
"msg": "Field constraints violation: string cannot be empty",
"type": "value_error.str.min_length"
}
]
}