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

POST /api/investors/me/2fa/disable-request — Запрос выключения 2FA (requestDisableTwoFactor)

Назначение

Первый шаг выключения двухфакторной аутентификации: отправить СМС-код на текущий телефон пользователя и создать запрос подтверждения с целью DisableTwoFactor (INV-7: выключение — только по подтверждению кодом, защита от отключения 2FA угнанным токеном). Вызывается аутентифицированным пользователем. Выключение применит confirm-disable-two-factor.md.

Metadata

ПолеЗначение
Сервис/контекстidentity
API areapublic
Feature groupsecurity
Статусapproved
Документdocs/06-services/identity/api/investor/request-disable-two-factor.md

Актор и доступ

ПроверкаЗначение
Actor typeUser (Bearer JWT)
Auth policy / Permissionsauthenticated; permission identity.security.manage-self
Scope (RBAC)self
Record-levelтолько собственная запись; код — только на телефон владельца
Tenant isolationне применяется (ADR-0052)
Auditsecurity-sensitive: факт запроса логируется

HTTP-контракт

ПолеЗначение
MethodPOST
Route/api/investors/me/2fa/disable-request
Success status200
Idempotency headerне применяется (повтор гасит предыдущий Pending — INV-S1 Superseded)
Correlationсквозной trace через traceparent

Входные данные / параметры запроса

Body отсутствует.

ПолеИсточникТипОбязательностьВалидация / ОграниченияБезопасность
UserIdidentity claims (sub)GuidДавалидный JWT401 без токена
IpAddress / UserAgentmiddlewarestring?Нет≤ 45 / ≤ 512rate-limit / анти-фрод

Модель ответа RequestDisableTwoFactorCommandResult

ПолеТипОбязательностьИсточникMaskingОписание
twoFactorConfirmationRequestIdstring (Guid)ДаSignInConfirmationRequest.IdИдентификатор запроса подтверждения.
realConfirmationCodeDispatchedboolДаverifierfalse — код не отправлялся реально (тестовый контур).

Алгоритм

  1. Контекст и доступ. Операцию выполняет аутентифицированный пользователь над собственной записью (UserId из токена); из middleware известны IpAddress/UserAgent.
  2. Проверка и лимиты. Rate-limit (INV-S4) — превышение ⇒ IDENTITY_CONFIRMATION_RATE_LIMITED (429).
  3. Проверки состояния. Получить пользователя; он Active — иначе IDENTITY_USER_BLOCKED; 2FA включена — иначе IDENTITY_TWO_FACTOR_NOT_ENABLED.
  4. Правила и маппинг. Сгенерировать код (CSPRNG); создать запрос подтверждения (INV-S8): цель DisableTwoFactor, UserId, PhoneNumber = телефон пользователя, хэш кода (HMAC-SHA256), ExpiresAt = now + 5 мин, IpAddress, UserAgent; фиксируется доменное событие ConfirmationCodeRequestedEvent (→ СМС-verifier).
  5. Что меняется. В одном согласованном изменении: прежний активный (Pending) запрос той же цели гасится в Superseded (INV-S1) и создаётся новый запрос.
  6. События. Интеграционных нет; доменное ConfirmationCodeRequestedEvent → СМС-verifier.
  7. Результат. twoFactorConfirmationRequestId, realConfirmationCodeDispatched; HTTP 200.

Диаграмма

Побочные эффекты

ТипДетали
Интеграционные событияnone
Внешние вызовыСМС-verifier (timeout 5 с, 1 retry)
Проекции / поискrate-limit-счётчик
УведомленияСМС с кодом

Предусловия и постусловия

  • Пред: пользователь аутентифицирован и Active; 2FA включена (IsTwoFactorEnabled = true); телефон подтверждён (код уходит на текущий номер владельца, вход не принимается).
  • Пост (успех): создан Pending-запрос цели DisableTwoFactor (TTL 5 мин); прежний Pending той же цели погашен в Superseded (INV-S1); СМС-код отправлен через verifier. IsTwoFactorEnabled не меняется — выключение применит только confirm-disable-two-factor.md по коду (INV-7). Интеграционные события не публикуются.

Acceptance Criteria

  • Given Active-пользователь с включённой 2FA, When POST .../2fa/disable-request, Then создан Pending-запрос DisableTwoFactor, код отправлен на текущий телефон владельца, ответ 200 с twoFactorConfirmationRequestId и realConfirmationCodeDispatched; IsTwoFactorEnabled не тронут.
  • Given уже есть активный Pending-запрос DisableTwoFactor, When повторный запрос, Then прежний переходит в Superseded (INV-S1), создаётся новый, отправляется новый код (в тест-контуре realConfirmationCodeDispatched = false).
  • Given 2FA не включена, When запрос, Then IDENTITY_TWO_FACTOR_NOT_ENABLED (400).
  • Given учётка Blocked/Archived, When запрос, Then IDENTITY_USER_BLOCKED (400).
  • Given превышен лимит отправки кода (INV-S4), When запрос, Then IDENTITY_CONFIRMATION_RATE_LIMITED (429), retry ≥ 60 сек.
  • Given verifier отказал после retry, When запрос, Then IDENTITY_SMS_DISPATCH_FAILED (400).
  • Given запрос без валидного JWT, When запрос, Then 401, клиент уходит на re-login.

Ошибки и failure modes

КодHTTP statusУсловиеСообщениеRetry
— (auth)401Нет/просрочен JWTклиент выполняет re-loginre-login
IDENTITY_TWO_FACTOR_NOT_ENABLED4002FA не включена«2FA не включена»no retry
IDENTITY_USER_BLOCKED400Status != Active«Учётная запись заблокирована»no retry
IDENTITY_CONFIRMATION_RATE_LIMITED429INV-S4«Слишком много запросов кода»retry ≥ 60 сек
IDENTITY_SMS_DISPATCH_FAILED400Отказ verifier«Не удалось отправить код»retry

Совместимость и наблюдаемость

  • Logs: UserId; metrics: identity_2fa_disable_requests_total; traces — OTel.

Обратные ссылки

Автоссылки: где используется этот документ.

Связанные документы