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

Документация API: Аутентификация пользователя (Login) с генерацией JWT, содержащего JWT Claims

Published

July 2, 2026

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

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

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

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

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

В рамках новой архитектуры этот метод выполняет роль транслятора контекста безопасности (Security Context Provider):

  1. Генерация токена сессии: Проверяет хэш пароля в СУБД и генерирует криптографически подписанный Access Token (JWT) [2026-07-02].
  2. Внедрение JWT Claims: Содержит внутри Payload токена параметры home_group_id, account_type и user_id. Это избавляет основные транзакционные микросервисы (Cook, Consume, Waste) от необходимости делать лишние JOIN-запросы в базу данных пользователей при каждом списании продуктов, так как шлюз FastAPI вычитывает контекст группы прямо из расшифрованного токена.

2 Протокол взаимодействия (HTTP Контракт)

  • Метод: POST
  • Маршрут: /api/v1/auth/login
  • Формат данных: application/json

2.1 Спецификация заголовков (HTTP Headers)

Заголовок Обязательный Описание Пример значения
Content-Type Да Формат передаваемых данных application/json
X-Request-ID Да Сквозной ID запроса для трассировки сессии авторизации req-auth-log-44bb

2.2 Спецификация тела запроса (Request Body)

Параметр Тип Обязательный Описание Пример значения
username String Да Уникальный логин пользователя (его email-адрес) user@somedomain.kz
password String Да Сырой текстовый пароль для сверки хэша MySecretPassword123

2.2.1 Пример сырого JSON-запроса (Payload):

{
  "username": "user@somedomain.kz",
  "password": "MySecretPassword123"
}

2.3 Спецификация успешного ответа (Response Body)

2.3.1 HTTP 200 OK

Возвращается при успешном совпадении учетных данных.

{
  "status": "success",
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJ1c3ItODgyMiIsImhvbWVfZ3JvdXBfaWQiOiJncm91cC03NzItYWxwaGEiLCJhY2NvdW50X3R5cCI6IkhPTUUiLCJleHAiOjE3ODMzMDk2MDB9.signature...",
  "expires_in": 3600
}

3 Диаграмма последовательности (Mermaid)

На диаграмме представлена логика аутентификации. Сервис Authorization сверяет хэш пароля в PostgreSQL, извлекает параметры привязки к пространству и генерирует JWT-токен, содержащий зашитые JWT Claims.

4 Вариант 2

4.1 Анатомическая структура декодированного JWT Payload (Claims):

Когда транзакционный бэкенд или сторонний ИИ-микросервис расшифровывают токен, они без обращения к БД видят следующий стандартизированный JSON-датасет:

{
  "sub": "usr-8822-fa41",
  "home_group_id": "group-772-alpha",
  "account_type": "HOME",
  "iss": "auth-service",
  "iat": 1783306000,
  "exp": 1783309600
}

5 Схема обработки запроса пользователя (Mermaid)

На диаграмме представлена логика аутентификации. Сервис Authorization сверяет хэш пароля в PostgreSQL, извлекает параметры привязки к пространству и генерирует JWT-токен, содержащий зашитые JWT 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 DB as DB_AUTH (PostgreSQL)

    App->>Nginx: Шаг 1: POST /api/v1/auth/login (email, password)
    activate Nginx
    Nginx->>GW: Шаг 2: POST /backend-api/v1/auth/login
    activate GW
    GW->>Auth: Шаг 3: gRPC: LoginUser(LoginRequest)
    activate Auth
    
    Auth->>DB: Шаг 4: SQL SELECT id, password_hash FROM users...
    activate DB
    DB-->>Auth: Шаг 5: Возврат хэша пароля
    deactivate DB
    
    note over Auth: Шаг 5 (продолжение):<br/>Крипто-валидация пароля
    note over Auth: Шаг 6: Генерация TokenPair<br/>с инъекцией Claims (home_group_id, account_type)
    
    Auth->>DB: Шаг 7: SQL INSERT INTO user_sessions...
    activate DB
    DB-->>Auth: Подтверждение записи сессии
    deactivate DB
    
    Auth-->>GW: Шаг 8: gRPC: LoginResponse
    deactivate Auth
    GW-->>App: Шаг 9: HTTP 200 OK (access, refresh)
    deactivate GW
    deactivate Nginx
    
    note over App: Шаг 10: Внутренний метод<br/>SecureStorage.write(...)

Процесс авторизации пользователя (Login) с обогащенными JWT Claims

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

Шаг Действие Параметры / Запросы / DTO Ошибки (Исключения / Статусы)
Шаг 1 (App -> Nginx) Клиент отправляет учетные данные пользователя на эндпоинт аутентификации. HTTP POST /api/v1/auth/login
Payload (UserAuthRequestDTO):
{ "email": "user@example.com", "password": "secure_password" }
DioException: send timeout
HTTP 400 Bad Request (некорректный формат email)
HTTP 429 Too Many Requests (лимит Rate Limit)
Шаг 2 (Nginx -> Gateway) Прокси-сервер выполняет базовую маршрутизацию запроса на шлюз. HTTP POST /backend-api/v1/auth/login
Headers:
X-Request-ID: "trace-auth-lifecycle-uuid"
HTTP 502 Bad Gateway (контейнер backend-api недоступен)
HTTP 504 Gateway Timeout
Шаг 3 (Gateway -> Auth) API-шлюз транслирует запрос во внутреннюю сеть через удаленный вызов процедур. Протокол: gRPC
Метод: LoginUser(LoginRequest)
Параметры: email, password
gRPC Status: UNAVAILABLE (сервис авторизации недоступен)
gRPC Status: INVALID_ARGUMENT
Шаг 4 (Auth -> DB_Auth) Сервис запрашивает из PostgreSQL данные для проверки существования пользователя и сверки пароля. SQL-запрос:
SELECT id, password_hash FROM users WHERE email = 'user@example.com' LIMIT 1;
PostgreSQL Exception: ConnectionPoolTimeout
PostgreSQL Exception: CommandTimeout
Шаг 5 (DB_Auth -> Auth) База данных возвращает результат поиска для валидации хэша в памяти сервиса. Набор данных СУБД (RecordSet): id (UUID) и строка password_hash (Bcrypt/Argon2). PostgreSQL Exception: DatabaseIsShuttingDown
gRPC Status: NOT_FOUND (пользователь не найден)
Шаг 5 (продолжение) (Auth -> Auth) Внутренняя проверка соответствия введенного пароля и хэша из БД. Криптографическая валидация (сравнение соли и хэша в памяти сервиса). gRPC Status: UNAUTHENTICATED (пароль неверный)
Шаг 6 (Auth -> Auth) Сервис генерирует пару токенов, внедряя в Access Token бизнес-контекст пользователя для оптимизации межсервисных запросов. Внутренний метод: GenerateTokenPair(user_id).
JWT Claims Payload:
{ "user_id": "uuid", "home_group_id": "uuid", "account_type": "premium" }
CryptoException: KeySigningError (ошибка доступа к приватному ключу подписи)
Шаг 7 (Auth -> DB_Auth) Сервис сохраняет созданную сессию (или Refresh-токен) в базу данных. SQL-запрос:
INSERT INTO user_sessions (user_id, refresh_token_hash, expires_at) VALUES ('user-uuid', 'hash...', '2026-08-27');
PostgreSQL Exception: UniqueViolation (конфликт UUID сессии)
PostgreSQL Exception: DiskFull
Подтверждение (DB_Auth -> Auth) База данных подтверждает успешную фиксацию строки сессии. Ответ СУБД: Статус INSERT 0 1 (успешная запись 1 строки). PostgreSQL Exception: TransactionAborted
Шаг 8 (Auth -> Gateway) Сервис возвращает структуру с токенами обратно на API-шлюз. Протокол: gRPC
Ответ: LoginResponse
Payload: access_token, refresh_token
gRPC Status: INTERNAL (ошибка маршаллинга gRPC-сообщения)
Шаг 9 (Gateway -> App) Шлюз транслирует успешный HTTP-ответ с токенами через Nginx на устройство клиента. HTTP Статус 200 OK
Payload:
{ "access": "eyJhbGci...", "refresh": "def456..." }
DioException: receive timeout (клиент потерял сеть в момент ответа)
Шаг 10 (App -> App) Мобильное приложение изолированно и персистентно сохраняет токены на устройстве. Внутренний метод: SecureStorage.write(...)
Запись в iOS Keychain или Android Keystore.
SecureStorageException (ошибка аппаратного модуля шифрования)
  • sub (Subject) — уникальный user_id автора операции для логирования действий.
  • home_group_id — UUID/строковый идентификатор целевого холодильника семьи или офиса. По нему фильтруются все SQL-запросы WHERE home_group_id = $1.
  • account_type — флаг контура (HOME или OFFICE), управляющий настройками “цифрового холодильника”.
  • exp (Expiration Time) — время жизни токена (3600 секунд / 1 час), по истечении которого App обязан запустить фоновое обновление сессии.