Перейти к содержанию

Авторизация

В платформе DataHUB два вида субъектов, которые проходят авторизацию: адаптеры (клиентские системы, вызывающие Exchange API) и пользователи Личного кабинета. Механизмы разные: адаптеры используют JWT Bearer-токены, пользователи — полный сеансовый flow с регистрацией, 2FA и управлением паролем.


Авторизация адаптеров

Каждый адаптер получает учётные данные (логин и пароль) из Личного кабинета и использует их для первичного входа. Далее сессия поддерживается парой токенов.

Токен Назначение
Access token Передаётся в заголовке Authorization: Bearer <token> при каждом запросе к Exchange API
Refresh token Используется для получения новой пары токенов; в обычных запросах не передаётся

Первичная авторизация — по username или email:

POST /api/auth/login/username  { username, password }
POST /api/auth/login/email     { email, password }

Ответ 200 OK:

{
  "accessToken": "eyJ...",
  "accessTokenExpiresAt": "2025-...",
  "refreshToken": "eyJ...",
  "refreshTokenExpiresAt": "2025-..."
}

Жизненный цикл токенов в адаптере:

  1. При запуске — авторизация по логину/паролю, сохранение токенов.
  2. При каждом запросе — Authorization: Bearer <accessToken>.
  3. При ответе 401 Unauthorized — обновление через /api/auth/refresh.
  4. Если refresh истёк — повторная авторизация по логину/паролю.
POST /api/auth/refresh  { refreshToken }   → 200  { accessToken, refreshToken }
POST /api/auth/logout   { refreshToken }   → 200

После logout оба токена инвалидируются на сервере.

Необязательный заголовок X-Device-ID позволяет привязать сессию к конкретному устройству или экземпляру адаптера. Если не передан — сервер генерирует fingerprint из User-Agent и IP.

В 1С-модуле токены хранятся в регистрах сведений модуля.


Авторизация пользователей Личного кабинета

Регистрация

sequenceDiagram
    participant U as Пользователь
    participant B as backend

    U->>B: POST /api/auth/register {email, password, confirmPassword}
    alt email уже занят
        B-->>U: 409 Conflict
    else OK
        B-->>U: 200 {requestId, confirmMethod, retryAfterSeconds}
        Note over B,U: письмо с кодом подтверждения отправлено
        U->>B: POST /api/auth/register/verify-email/confirm {requestId, token}
        alt неверный код
            B-->>U: 400 {attemptsRemaining}
        else превышен лимит
            B-->>U: 429 Too Many Requests
        else OK
            B-->>U: 200 LoginSuccessResponseDto
        end
    end

Повторная отправка кода: POST /api/auth/register/verify-email/resend { requestId }.

После успешного подтверждения email пользователь получает токены и попадает в flow проверки состояния профиля (см. Состояние после входа).

Вход

Два равнозначных эндпоинта — по email или по username:

POST /api/auth/login/email     { email, password }
POST /api/auth/login/username  { username, password }
sequenceDiagram
    participant U as Пользователь
    participant B as backend

    U->>B: POST /api/auth/login/email {email, password}
    alt аккаунт заблокирован (5+ неверных попыток)
        B-->>U: 423 Locked + lockedUntil
    else email не подтверждён
        B-->>U: 409 Conflict + {requestId, retryAfterSeconds}
        Note over U: форма подтверждения email
    else истёк срок действия учётных данных
        B-->>U: 401 Unauthorized + ACTION_RESET_PASSWORD
    else 2FA включена
        B-->>U: 428 Precondition Required + {requestId, confirmMethod}
        Note over U: SMS-код отправлен
        U->>B: POST /api/auth/login/two-factor/confirm {requestId, token}
        alt код истёк
            B-->>U: 400 {attemptsRemaining}
        else превышен лимит
            B-->>U: 429 Too Many Requests
        else OK
            B-->>U: 200 LoginSuccessResponseDto
        end
    else успешно
        B-->>U: 200 LoginSuccessResponseDto
    end

Повторная отправка кода 2FA при входе: POST /api/auth/login/two-factor/resend { requestId }.

Состояние пользователя после входа

LoginSuccessResponseDto содержит вложенный объект userDto с флагами состояния. Фронтенд читает эти флаги и определяет следующий шаг:

Флаг в userDto Значение Действие фронтенда
profileIncompleted: true Профиль не заполнен Редирект на /welcome — форма с полями firstName, lastName, phone; вызов PATCH /api/users/me
resetPasswordRequired: true Администратор установил требование смены пароля Токены выданы с ролью USER_PASSWORD_RESET_REQUIRED; пользователь может сменить пароль в профиле через PATCH /api/users/change-password
Все флаги false Нормальное состояние Редирект на /bus

Флаг resetPasswordRequired выставляется администратором в панели управления пользователями. Автоматического принудительного редиректа при входе фронтенд в текущей версии не реализует.

Включение двухфакторной аутентификации

Для аутентифицированного пользователя:

sequenceDiagram
    participant U as Пользователь
    participant B as backend

    U->>B: PATCH /api/users/two-factor-authentication
    B-->>U: 200 {requestId, confirmMethod, retryAfterSeconds}
    Note over B,U: SMS-код отправлен
    U->>B: POST /api/users/two-factor-authentication/confirm {requestId, token}
    alt код истёк
        B-->>U: 400 {attemptsRemaining}
    else превышен лимит
        B-->>U: 429 Too Many Requests
    else OK
        B-->>U: 200 OK — 2FA включена
    end

Повторная отправка кода: POST /api/users/two-factor-authentication/resend { requestId }.

Отключение 2FA: DELETE /api/users/two-factor-authentication.

Сброс пароля

sequenceDiagram
    participant U as Пользователь
    participant B as backend

    U->>B: POST /api/auth/reset-password {email}
    B-->>U: 200 {requestId, retryAfterSeconds}
    Note over B,U: письмо с кодом отправлено (даже если email не найден)
    U->>B: POST /api/auth/reset-password/confirm {requestId, token, newPassword, confirmPassword}
    alt неверный код
        B-->>U: 400 {attemptsRemaining}
    else превышен лимит
        B-->>U: 429 Too Many Requests
    else OK
        B-->>U: 200 {confirmed: true}
    end

Запрос инициируется независимо от того, найден ли email в системе — это исключает возможность перечисления пользователей.


Коды ответов

Код Ситуация
200 OK Успех; тело зависит от операции
400 Bad Request Неверный или истёкший код подтверждения; поле attemptsRemaining
401 Unauthorized Истёк срок действия учётных данных; включает ACTION_RESET_PASSWORD
403 Forbidden Аккаунт отключён или истёк
409 Conflict Email или телефон не подтверждён; включает requestId для повторной отправки
423 Locked Аккаунт заблокирован после превышения числа неверных попыток
428 Precondition Required Требуется подтверждение 2FA; включает requestId и confirmMethod
429 Too Many Requests Превышен лимит запросов; заголовки Retry-After, X-Rate-Limit-*