Авторизация
В платформе DataHUB два вида субъектов, которые проходят авторизацию: адаптеры (клиентские системы, вызывающие Exchange API) и пользователи Личного кабинета. Механизмы разные: адаптеры используют JWT Bearer-токены, пользователи — полный сеансовый flow с регистрацией, 2FA и управлением паролем.
Авторизация адаптеров
Каждый адаптер получает учётные данные (логин и пароль) из Личного кабинета и использует их для первичного входа. Далее сессия поддерживается парой токенов.
| Токен | Назначение |
|---|---|
| Access token | Передаётся в заголовке Authorization: Bearer <token> при каждом запросе к Exchange API |
| Refresh token | Используется для получения новой пары токенов; в обычных запросах не передаётся |
Первичная авторизация — по username или email:
Ответ 200 OK:
{
"accessToken": "eyJ...",
"accessTokenExpiresAt": "2025-...",
"refreshToken": "eyJ...",
"refreshTokenExpiresAt": "2025-..."
}
Жизненный цикл токенов в адаптере:
- При запуске — авторизация по логину/паролю, сохранение токенов.
- При каждом запросе —
Authorization: Bearer <accessToken>. - При ответе
401 Unauthorized— обновление через/api/auth/refresh. - Если 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:
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-* |