Моя среда 2ФА
Подключение двухфакторной аутентификации к проекту через server-side API. Сайт управляет проектами, ключами, статистикой и проверкой кодов; текущие TOTP-коды генерирует только мобильное приложение.
TOTP
server-side verify
Flutter authenticator
Модель работы
Что находится на сайте, а что в приложении
Сайт Моя среда 2ФА
- Создает проект и API key/secret.
- Выдает `otpauth://` URI при подключении пользователя.
- Проверяет первый код через confirm.
- Проверяет входы через verify и ведет статистику.
Мобильное приложение
- Входит в отдельный личный аккаунт пользователя по email-коду, не в аккаунт владельца проекта.
- Сканирует QR или принимает manual key.
- Хранит секрет локально в защищенном хранилище.
- Генерирует 6-значный TOTP-код каждые 30 секунд.
- Не отправляет секреты в облако и не требует интернет для генерации кода.
Мобильное приложение
Личный аккаунт пользователя
Вход и безопасность
- Аккаунт приложения отделен от аккаунта владельца проекта на
dev-sreda.ru. - Вход выполняется по email-коду; если письмо не пришло, пользователю нужно проверить папку "Спам".
- После входа пользователь задает 4-значный PIN и может включить отпечаток пальца.
- Чувствительные настройки подтверждаются PIN или биометрией.
Устройства приложения
- Пользователь может выйти из текущей сессии приложения.
- В настройках доступен список активных устройств личного аккаунта.
- Сессию другого устройства можно завершить без раскрытия токенов, IP и технических деталей.
- Удаление личного аккаунта приложения очищает app-токены; локальные TOTP-коды на текущем устройстве удаляются приложением.
- E2E-резервная копия хранится на сервере только как зашифрованный контейнер; ключ восстановления сервер не получает.
Быстрый старт
Подключение проекта
- Активируйте инструмент Моя среда 2ФА и создайте проект в кабинете.
- Сохраните `project_key` и одноразово показанный `project_secret` в секретах вашего проекта.
- На странице включения 2FA у пользователя вызовите `enroll` и покажите QR из `otpauth_uri` или manual key.
- Попросите пользователя ввести код из мобильного приложения и отправьте его в `confirm`.
- При каждом следующем входе после пароля запрашивайте код и отправляйте его в `verify`.
- Для отключения 2FA используйте `disable` после свежего подтверждения пароля в вашем проекте.
Recovery
Сброс привязки пользователя
- Если пользователь потерял устройство, владелец проекта может сбросить его 2FA-привязку на странице проекта.
- Сброс требует текущий пароль владельца проекта и не показывает TOTP-секрет.
- После сброса пользователь проходит подключение заново: новый
enroll, QR-код, первый код иconfirm. - Внешний проект должен также требовать свежий пароль или другой фактор перед самостоятельным отключением 2FA через API.
API
Endpoint-ы
| Endpoint | Когда вызывать | Успешный результат |
|---|---|---|
POST /api/2fa/v1/enroll |
Пользователь начинает подключение 2FA. | otpauth_uri, manual_key, enrollment_id |
POST /api/2fa/v1/confirm |
Пользователь ввел первый код из приложения. | recovery_codes, которые нужно показать один раз |
POST /api/2fa/v1/verify |
Проверка кода при входе или важном действии. | success: true |
POST /api/2fa/v1/disable |
Отключение 2FA после подтверждения пользователя. | success: true |
Пример
Laravel backend
Enroll
Http::timeout(5)->asJson()->post('/api/2fa/v1/enroll', [
'project_key' => config('services.sreda_2fa.key'),
'project_secret' => config('services.sreda_2fa.secret'),
'external_user_id' => (string) $user->id,
'account_name' => $user->email,
]);
Verify
$response = Http::timeout(5)->asJson()->post('/api/2fa/v1/verify', [
'project_key' => config('services.sreda_2fa.key'),
'project_secret' => config('services.sreda_2fa.secret'),
'external_user_id' => (string) $user->id,
'code' => $request->input('code'),
]);
abort_unless($response->json('success') === true, 422);
Безопасность
Обязательные правила интеграции
- Храните `project_secret` только в `.env` или секретном хранилище.
- Не сохраняйте `manual_key`, `otpauth_uri`, recovery-коды и пользовательские TOTP-коды в логах.
- Не включайте 2FA до успешного `confirm`; pending enrollment имеет короткий срок жизни.
- Запрашивайте текущий пароль перед отключением 2FA или заменой устройства.
- Используйте HTTPS и нейтральные ошибки, не раскрывающие существование аккаунта.
- Recovery-коды показывайте пользователю один раз и храните у себя только хеши, если реализуете локальное зеркало.