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

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

Published

July 2, 2026

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.

sequenceDiagram
    autonumber
    actor User as Пользователь (Экран Авторизации)
    participant APP as Мобильное приложение (Flutter)
    participant AS as Сервис Авторизации (FastAPI)
    participant DB as Реляционная СУБД (PostgreSQL)

    User->>APP: Вводит email/пароль, нажимает "Войти"
    APP->>AS: HTTP POST /api/v1/auth/login (JSON с username и password)
    activate AS
    
    AS->>DB: SELECT id, password_hash, home_group_id, account_type FROM users WHERE email = username
    activate DB
    DB-->>AS: Возвращает метаданные и хэш пароля пользователя
    deactivate DB
    
    note over AS: Шаг 5: Сверка хэша пароля (Bcrypt/Argon2)
    
    alt Хэши совпали (Успешный вход)
        note over AS: Шаг 6: Генерация JWT и упаковка Claims (home_group_id, account_type)
        AS-->>APP: HTTP 200 OK (status: "success", token: "eyJ...", expires_in: 3600)
    else Пароль неверный ИЛИ пользователь не найден
        AS-->>APP: HTTP 401 Unauthorized (ERR-INVALID-CREDENTIALS)
    end
    deactivate AS
    note over APP: Flutter сохраняет токен в Secure Storage и открывает экран Холодильника

4 Расшифровка шагов и Анатомия JWT Payload

  • Шаг 1 (User -> APP): Пользователь на форме входа вводит свой email (в поле username) и пароль, после чего нажимает кнопку «Войти».
  • Шаг 2 (APP -> AS): Мобильное приложение упаковывает учетные данные в JSON и отправляет запрос HTTP POST /api/v1/auth/login. В заголовках передается сквозной X-Request-ID.
  • Шаг 3 (AS -> DB): Микросервис Авторизации (FastAPI) принимает запрос и обращается к базе данных: SELECT id, password_hash, home_group_id, account_type FROM users WHERE email = $1.
  • Шаг 4 (DB -> AS): СУБД возвращает строку пользователя, включая хэшированный пароль и параметры Multi-Tenancy изоляции (к какому холодильнику привязан юзер и по каким правилам работает этот контур).
  • Шаг 5 (AS -> AS): Метод проверяет соответствие сырого входящего пароля и хэша из базы данных с помощью криптографической библиотеки (Bcrypt/Argon2). Если пароли не совпадают, выполнение прерывается с возвратом ошибки HTTP 401.
  • Шаг 6 (AS -> AS): В случае успеха сервис генерирует строку Access Token по стандарту JWT (симметричное шифрование HS256 с использованием системного приватного ключа). Внутрь полезной нагрузки (Payload) токена жестко запекаются три наших архитектурных кита.

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
}
  • sub (Subject) — уникальный user_id автора операции для логирования действий.
  • home_group_id — UUID/строковый идентификатор целевого холодильника семьи или офиса. По нему фильтруются все SQL-запросы WHERE home_group_id = $1.
  • account_type — флаг контура (HOME или OFFICE), управляющий вилками ухода в виртуальный минус или жесткой блокировки дефицита.
  • exp (Expiration Time) — время жизни токена (3600 секунд / 1 час), по истечении которого Flutter-клиент обязан запустить фоновое обновление сессии.

5 Спецификация вилок исключений и обработки ошибок

При аутентификации система обрабатывает ошибки безопасности на Шаге 5, не раскрывая наружу, какая именно часть учетных данных была неверной. Это защищает контур от перебора логинов злоумышленниками.

5.1 1. Ошибка: Неверный логин или пароль (HTTP 401 Unauthorized)

Вызывается на Шаге 5, если хэш пароля не совпал, либо если указанный email полностью отсутствует в базе данных пользователей PostgreSQL.

  • Заголовки ответа (Response Headers):
    • Content-Type: application/json
  • Тело ответа (Response Body):
{
  "error_code": "ERR-INVALID-CREDENTIALS",
  "message": "Неверный логин или пароль. Доступ к системе отклонен.",
  "details": {
    "action": "Prompt user to re-enter credentials or trigger password recovery flow."
  }
}

5.2 2. Ошибка валидации формата email (HTTP 422 Unprocessable Entity)

Возвращается на Шаге 4 бэкенд-шлюзом FastAPI, если переданная строка в поле username не соответствует валидному синтаксису адреса электронной почты.

{
  "error_code": "ERR-VALIDATION-FAILED",
  "message": "Передан некорректный формат логина (требуется валидный email).",
  "details": [
    {
      "loc": ["body", "username"],
      "msg": "value is not a valid email address",
      "type": "value_error.email"
    }
  ]
}