К содержанию

ModTwoAuth: двухфакторная аутентификация для MODX 3 - TOTP, Email, Telegram и Passkeys

Я решил открыть доступ к ModTwoAuth, компонент двухфакторной аутентификации для MODX 3. Он добавляет второй шаг при входе в админку и в личный кабинет на сайте: код из приложения-аутентификатора, код на email, код или кнопка в Telegram, а также WebAuthn — Touch ID, Face ID, Windows Hello и аппаратные ключи. Админка и фронтенд включаются независимо друг от друга.



Что внутри

  1. Четыре метода второго фактора:
    • TOTP (RFC 6238)
    • Email
    • Telegram
    • WebAuthn / FIDO2 / Passkeys.
  2. Отдельные настройки для менеджера и для пользователей сайта, фронтенд совместим со сниппетом Login.
  3. Защита от перебора: 3 неверных кода блокируют вход на 15 минут. Состояние блокировки хранится в базе и переживает перезапуск PHP-процессов, тот же лимит действует при первоначальной настройке метода.
  4. TOTP-секреты лежат в базе только зашифрованными (libsodium XChaCha20-Poly1305), ключ шифрования — вне директории компонента.
  5. Список активных сессий с отзывом по одной и принудительным завершением сессий старше заданного возраста.
  6. QR-коды создаются локально в браузере встроенной библиотекой: одноразовые токены не уходят на за пределы.
  7. Диагностика безопасности прямо на главной странице компонента: ключ, sodium, HTTPS, флаги cookie, CSP, статус плагинов.

TOTP: код из приложения


Работает с Google Authenticator, Authy, Aegis и любым приложением по RFC 6238. На вкладке «🔐 2FA» в профиле пользователь жмёт «Сгенерировать QR», сканирует его телефоном и вводит текущий 6-значный код. После трёх неверных попыток секрет аннулируется — нужно запрашивать новый QR.

Секрет 160-битный, в базу попадает уже зашифрованным. Допускается расхождение часов на ±1 шаг (30 секунд), а принятый код запоминается по timestep и повторно не проходит: перехваченный или подсмотренный код через минуту уже бесполезен.

backend

Email: код на почту


Одноразовый 6-значный код уходит на подтверждённый адрес через почту MODX, достаточно настроенного SMTP. Код живёт modtwoauth_code_lifetime секунд (по умолчанию 300), между повторными отправками выдерживается пауза modtwoauth_resend_cooldown (60 секунд), чтобы кнопку «Отправить ещё раз» нельзя было жамкать бесконечно.

Тема и HTML-текст письма лежат в словарях modtwoauth_email_subject и modtwoauth_email_body, в них работают плейсхолдеры
[[+code]]
и
[[+minutes]]
Письмо можно переписать под свою вёрстку и перевести — словари в пакете есть на нескольких языках.

Telegram: код или одна кнопка


Самый удобный метод для у кого сервер не глушит ТГ, кто не хочет ставить приложение-аутентификатор. Вы создаёте бота как обычно в @BotFather и вписываете токен в modtwoauth_telegram_bot_token, остальное пакет делает сам: вебхук регистрируется автоматически при создании запроса на привязку или вход, секрет вебхука выводится из токена бота и проверяется на каждом запросе.

Пользователь сканирует QR или переходит по deep-link, нажимает Start, затем «Подтвердить подключение» в боте. Запрос одноразовый и живёт 5 минут, в базе хранятся только хеши токенов. При входе бот присылает 6-значный код и кнопки «Разрешить вход» / «Отклонить» — подтвердить может только тот чат, который привязан к аккаунту.

В Telegram одно жёсткое требование: сайт должен быть доступен из интернета по HTTPS. На localhost вебхук не зарегистрировать, поэтому метод удобнее проверять на боевом или тестовом сервере.

WebAuthn и Passkeys


Вход по отпечатку пальца, лицу или аппаратному ключу — вообще без кодов. Поддерживаются ES256, RS256 и Ed25519, residentKey и userVerification в режиме preferred, так что passkeys работают без заранее заведённого списка credentials. Ключей можно зарегистрировать несколько: телефон, ноутбук, YubiKey.

RP ID компонент определяет по хосту — manager_url для админки и site_url для фронтенда. Для нестандартных поддоменов задайте modtwoauth_webauthn_rp_id, туда можно вписать как example.com, так и полный URL. Счётчик подписей аутентификатора проверяется, поэтому склонированный ключ не пройдёт; у аутентификаторов без счётчика проверка пропускается. Тип аттестации — none, цепочка сертификатов вендора не проверяется, это осознанное решение.

WebAuthn тоже требует HTTPS, исключение — localhost.
frontend

Как включить в админке

Установите пакет через Приложения → Управление пакетами. Установщик создаст таблицы, сгенерирует ключ шифрования core/config/modtwoauth.key с правами 0600 и зашифрует TOTP-секреты, если они уже были сохранены открытым текстом.
В Системные настройки → ModTwoAuth включите modtwoauth_enable_2fa.

Каждый менеджер настраивает метод себе сам: Пользователи → своя учётная запись → вкладка «🔐 2FA» — QR, код из письма, привязка Telegram или регистрация Passkey, затем переключатель «Включить 2FA».

Со следующего входа MODX запросит код после пароля.

Важно: 2FA действует только для пользователей, которые настроили и включили метод. Включённая системная настройка сама по себе никого не заблокирует — можно спокойно включать компонент на работающем сайте и дать менеджерам время на настройку.

Страница подтверждения берётся из чанка modtwoauthVerifyTpl, её адрес задаётся настройкой modtwoauth_verify_url (по умолчанию /2fa). Если дружественные URL выключены, работает прямой адрес /assets/components/modtwoauth/verify.php.

Фронтенд: личный кабинет на двух сниппетах

Для пользователей сайта есть отдельная настройка modtwoauth_frontend_enable_2fa (по умолчанию включёна). В личном кабинете достаточно вывести два сниппета:

выбор и настройка метода

[[!ModTwoAuthFrontend]]
доступны параметра

&methods можно оставить только нужные методы (totp,email,telegram,webauthn), если оставить пустым покажутся все.
&tpl ID чанка-шаблона (по умолчанию `modtwoauthFrontendSettingsTpl`).

frontend

список активных сессий

[[!ModTwoAuthSessions]]
доступны параметра

&showCurrent скрыть текущую сессию из списка (по умолчанию 1).
&tpl ID чанка-шаблона (по умолчанию `modtwoauthSessionsTpl`).
список активных сессий

frontend

Оба работают только для авторизованных пользователей и в любом веб-контексте.

Сессии — то, ради чего я и создала пакет, так в TwoFactorX мне много чего не хватало. В списке видны IP, браузер и время последней активности, токены сессий в интерфейс не выводятся.

Чужую сессию можно отозвать одной кнопкой: запись удаляется, и при следующем запросе она завершится. Текущую сессию отозвать нельзя. Отключение 2FA требует ввода текущего пароля.

Страницу подтверждения на фронтенде можно оформить в своем стиле -укажите ID чанка в modtwoauth_verify_chunk_id. При пустом или неверном значении компонент показывает к стандартный шаблону, на админку эта настройка не влияет.

frontend

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

Отдельно про вещи, которые обычно всплывают при аудите:

Второй фактор передаётся только через штатные страницы подтверждения. Обойти его запросом с внешним флагом нельзя — таких флагов нет.

При блокировке вход отклоняется, а не «проваливается» в проверку пароля.

Коды из писем и Telegram хранятся только как bcrypt-хеши.

Все формы подтверждения защищены CSRF-токенами, коннектор и процессоры требуют POST и сверяют Origin/Referer, список действий коннектора-allowlist.

При включённой 2FA нельзя «тихо» перезаписать метод прямым вызовом процессора — сначала отключение через профиль.

ID сессии регенерируется после успешного второго фактора во всех потоках: менеджер, фронтенд, Telegram, WebAuthn.

Редиректы после 2FA проверяются по схеме, хосту и порту сайта, open redirect не получится.

Сообщения сервера экранируются перед вставкой в DOM, детали исключений пишутся только в журнал MODX.

После установки пройдитесь по чек-листу:

HTTPS на менеджере и сайте, session.cookie_secure=1 и session.cookie_httponly=1 в PHP, отчёты CSP Report-Only просмотрены в консоли браузера до включения блокирующей политики. Все пункты продублированы в диагностике на главной странице компонента — там сразу видно, чего не хватает.

Ключ шифрования

Ключ создаётся установщиком в core/config/modtwoauth.key. Обязательно сделайте копию: без ключа зашифрованные TOTP-секреты не восстановить, пользователям придётся делать перевыпуск (секреты email, Telegram и WebAuthn при этом не страдают).
Ключ можно вынести за пределы сайта — настройкой modtwoauth_key_path или переменной окружения MODTWOAUTH_KEY_PATH.

Если TOTP уже работает, не генерируйте новый ключ: сначала перенесите существующий файл, и только потом меняйте настройку.

Требования

MODX Revolution 3.x.
PHP 8.1+ с расширением sodium (входит в PHP по умолчанию с 7.2).
HTTPS — обязателен для Telegram-вебхука и WebAuthn.
ЧПУ для url /2fa и /2fa-web; без них работают прямые адреса.

Где взять

GitHub: github.com/vitos88/ModTwoAuth
Скачать: github.com/vitos88/ModTwoAuth/releases/tag/v1.0.0
Modx: extras.modx.com/package/modtwoauth
Modstore: добавлю когда восстановится
ВитОс
ВитОс
Сегодня в 02:45
modx.pro
60
Реклама

Комментарии: 0

Авторизуйтесь или зарегистрируйтесь, чтобы оставлять комментарии.
0