Перейти к основному содержимому

Безопасность

Зачем нужно

Документ описывает пользовательскую безопасность: сессии, методы входа, активность и смену пароля.

Целевая архитектура домена безопасности: сессии, аудит, методы входа. Статус: в разработке


1. Обзор

Подсистема identity security — тонкий HTTP-слой для раздела "Безопасность" в профиле пользователя. Бизнес-логика живёт в identity auth subsystemе, security предоставляет UI-ориентированные эндпоинты.

Ответственности:

  • Сессии — просмотр, отзыв (делегирует в auth SessionService)
  • Методы входа — просмотр, настройка, отвязка (делегирует в auth)
  • Активность — история security-значимых действий (чтение из audit_logs)
  • Смена пароля — из профиля (делегирует в auth PasswordService)

Не входит в security-домен:

  • Управление устройствами как отдельным продуктовым разделом; server-side device_bindings остаются частью auth/session безопасности
  • TOTP — шаг в auth flow воронке, управление через auth-methods API
  • OAuth-привязки — identity auth subsystem (user_auth_methods)
  • Генерация/ротация токенов — identity auth subsystem

2. Сессии

Сессия создаётся при каждом успешном входе. Хранится в БД (identity auth subsystem).

2.1. Поля сессии

ПолеТипОписание
idUUID PK
userIdUUID FK → usersВладелец
refreshTokenIdUUID FK → refresh_tokensПривязка к refresh token
deviceBindingIdUUID FK → device_bindingsОпциональная привязка к устройству
userAgentVARCHAR(500)?User agent при создании
ipAddressVARCHAR(50)?IP при создании
browserNameVARCHAR(100)?Название браузера
lastActivityAtTIMESTAMPTZОбновляется при refresh token
expiresAtTIMESTAMPTZ30 дней (совпадает с TTL refresh token)
isRevokedBOOLEANОтозвана ли

Сессия идентифицируется по refresh token. device_binding используется для saved accounts, child device authorizations и risk checks, но не заменяет refresh token.

2.2. Операции

ОперацияОписание
ПросмотрСписок активных сессий с пометкой current
Отзыв однойИнвалидирует refresh token + помечает isRevoked
Отзыв всех кроме текущейМассовый отзыв
АвтоочисткаCron: удаление истёкших сессий (auth TokenCleanupService)

2.3. Владение

SessionService живёт в identity auth subsystemе (identity auth session service). Security-контроллер делегирует в него.


3. Методы входа

Пользователь управляет привязанными методами входа в разделе "Безопасность":

  • Просмотр включённых методов (пароль, TOTP, SMS OTP, OAuth)
  • Настройка нового метода (setup + verify)
  • Отвязка метода (с ограничением: хотя бы один метод должен быть активен)

Хранение: таблица user_auth_methods (identity auth subsystem). TOTP secret — в user_auth_methods.settings (type: 'totp').


4. Активность

getActivity() — чтение security-значимых событий из audit_logs за последние 180 дней.

Фильтруемые действия:

  • Вход / выход
  • Смена пароля
  • Изменение методов входа
  • 2FA включение / отключение
  • Отзыв сессий
  • Изменение профиля (email, телефон, аватар, имя)
  • Приглашения (создание, принятие, отклонение)

Пагинация: cursor-based или offset (page + limit).


5. Смена пароля

Два пути (оба делегируют в auth PasswordService):

Путь 1 — из профиля (авторизован):

Безопасность → "Сменить пароль"
→ ввод старого + нового пароля
→ PasswordService.changePassword()

Путь 2 — "Забыл пароль" (без авторизации):

Экран входа → "Забыли пароль?"
→ VerificationCodeService → TransportRegistry → код
→ PasswordService.resetPassword()

Хеш пароля хранится в таблице user_credentials (identity auth subsystem), не в users.


6. API-эндпоинты

6.1. Сессии (JWT)

HTTPПутьНазначение
GET/api/v2/identity/security/sessionsСписок активных сессий
DELETE/api/v2/identity/security/sessions/:idОтозвать сессию
POST/api/v2/identity/security/sessions/revoke-allОтозвать все кроме текущей

6.2. Методы входа (JWT)

HTTPПутьНазначение
GET/api/v2/identity/security/auth-methodsСписок привязанных методов
POST/api/v2/identity/security/auth-methods/:type/setupНачать настройку метода
POST/api/v2/identity/security/auth-methods/:type/verifyПодтвердить настройку
DELETE/api/v2/identity/security/auth-methods/:typeОтвязать метод

6.3. Пароль (JWT)

HTTPПутьНазначение
POST/api/v2/identity/auth/password/changeСменить пароль (старый + новый) → делегирует в identity auth subsystem

6.4. Активность (JWT)

HTTPПутьНазначение
GET/api/v2/identity/security/activityИстория безопасности

7. Серверная структура

7.1. Целевая структура

apps/identity-api/src/security/
├── security.controller.ts # HTTP-эндпоинты "Безопасности"
└── security.module.ts # Импортирует AuthModule, AuditModule

Вся бизнес-логика — в identity auth subsystemе. Security-контроллер — тонкий слой, делегирующий вызовы.

7.2. Зависимости

SecurityController
├── SessionService (auth)
├── PasswordService (auth)
├── AuthMethodRegistry (auth / plugins)
└── AuditService

8. Связи с другими доменами

ДоменСвязь
authSessionService, PasswordService, AuthMethodRegistry — вся бизнес-логика
platform notificationsУведомления о security-событиях через NATS JetStream → NotificationOrchestrator
auditЧтение audit_logs для истории активности
pluginsAuth method plugins (TOTP, SMS OTP) через AuthMethodRegistry

9. Организационная безопасность

Организации являются identity-owned access/context layer. Все действия, которые меняют ownership, membership, roles, grants, students или merge state, audit-required.

Правила:

  • ownership claims проходят ручную проверку «Систематики»;
  • organization merge доступен только system admin и требует impact preview;
  • automatic merge запрещён;
  • permission grants создаются и отзываются только с audit;
  • доступ к organization_students требует active membership и catalog permission;
  • заявки на владение могут содержать чувствительные данные, поэтому evidence links не логируются как raw PII;
  • break-glass доступ super_admin к organization карточке всегда audit-required;
  • organization_reference не даёт прав и не должен использоваться как authorization source;
  • product permissions остаются в доменах-владельцах, identity не принимает локальные permissions вроде olympiad.* или problem_bank.*;
  • organization_student нельзя показывать вне organization scope без явного product permission или service scope.
  • educator_profile, заявленная организация и trust status не дают доступ к чужим группам, официальной статистике организации или официальному контуру организации;
  • самозаявленный преподаватель может работать только со своими learning_group_participant через LMS permissions;
  • площадочный доступ проверяется как competitions product permission в scope выбранной организации, а не как отдельный identity user context;
  • родительский режим не отправляет олимпиадную работу как ребёнок без явного детского режима/delegated flow и audit с adult actor.


10. UX/UI

10.1. SecurityPage — структура

Страница /:lang/security внутри DashboardLayout (maxContentWidth: 520px). Навигация табами (underline style):

ТабСодержимое
ОбзорSecurityScoreCard + методы входа + текущая сессия
СессииТаблица активных сессий
УстройстваСписок доверенных устройств
АктивностьИстория входов и действий
ВосстановлениеМетоды восстановления доступа

Табы фильтруются через usePageBlocks("security") — администратор может скрывать отдельные табы.

10.2. Таб "Обзор"

SecurityScoreCard:

  • Кольцевой индикатор 0–100 + 10-сегментная полоса
  • Цветовая кодировка: зелёный (≥70) / жёлтый (45–69) / красный (<45)
  • Алгоритм: TOTP + второй фактор = 95, только TOTP = 72, без 2FA = 45

Методы входа:

  • Список строк SecurityListItem: иконка + название метода + Switch тумблер
  • Пароль — базовый local login method; может отсутствовать или быть выключен для OAuth-only/passwordless/SSO сценариев, строка "Сменить пароль" показывается только если password credential существует
  • TOTP — опциональный. Включение → TotpSetupModal
  • Другие методы — через AuthMethodsModal

Текущая сессия:

  • Строка с информацией об устройстве (браузер, ОС, IP)

10.3. TotpSetupModal

Модалка настройки TOTP:

  1. QR-код для сканирования приложением-аутентификатором
  2. Текстовый секретный ключ (копируемый)
  3. Поле ввода 6-значного кода для подтверждения (CodeInput)
  4. Кнопка "Подтвердить"

10.4. ChangePasswordModal

  • Поле: текущий пароль
  • Поле: новый пароль + индикатор сложности (PasswordStrengthIndicator)
  • Поле: подтверждение нового пароля
  • Кнопки: "Сменить" / "Отменить"

10.5. Таб "Сессии"

SessionsTab (lazy-loaded):

  • Таблица: устройство, браузер, IP, местоположение, последняя активность
  • Текущая сессия выделена бейджем "Текущая"
  • Кнопка "Завершить" для каждой сессии (кроме текущей)
  • Кнопка "Завершить все кроме текущей"

10.6. Таб "Устройства"

DevicesTab (lazy-loaded):

  • Список доверенных устройств
  • Каждое устройство: иконка типа (desktop/mobile/tablet) + название + дата последнего входа
  • Кнопка "Удалить" для каждого устройства

10.7. Таб "Активность"

ActivityHistoryTab (lazy-loaded):

  • Хронологический список событий
  • Каждое событие: иконка типа + описание + IP + дата/время
  • Типы: вход, выход, смена пароля, включение 2FA, неудачная попытка входа

10.8. Таб "Восстановление"

RecoveryMethodsTab (lazy-loaded):

  • Список методов восстановления: email, телефон, резервные коды
  • Для каждого: статус (настроен/не настроен) + действие (настроить/изменить)