Passkeys в WordPress и WooCommerce: плагины и подводные камни

«Установить плагин — и логин по отпечатку» — так это не работает. Когда веб-мастер решает «внедрить passkeys в WordPress», он ожидает, что задача решается в меню «Плагины → Добавить новый». На самом деле в экосистеме WordPress под беспарольным входом прячутся три разных вещи с разным устройством, разным качеством и разным порогом боли — и главный подводный камень вообще не про плагины, а про ваш хостинг. Эта статья — третья в серии (после криптографии простыми словами и внедрения на PHP/JS); здесь мы смотрим не на WebAuthn-стандарт, а на конкретный ландшафт WordPress и WooCommerce на момент написания.

Главный честный тезис: официальный плагин Two Factor сам по себе passkey не даёт — legacy FIDO U2F из него удалили в версии 0.16.0 (27 марта 2026) после потери поддержки браузерами, и чтобы получить WebAuthn/passkey поверх него, нужен отдельный провайдер. А реальный барьер к внедрению — не криптография и не «безопасно ли это», а инфраструктура: нужные PHP-расширения, HTTPS и то, что верификация подписи WebAuthn — это CPU-ёмкая асимметричная операция, которую shared-хостинг троттлит по CPU.

Версии плагинов и API в этой теме двигаются быстро: каждая конкретная цифра/версия ниже названа с датой и оговоркой «переснять по источнику». Код абстрактный (домены условные example.test), без привязки к какому-либо продукту.


Часть I. Ландшафт: под «passkeys» в WordPress лежат два разных подхода

Первая путаница — думать, что «плагин passkeys» это одна категория. На самом деле плагины делятся по тому, какую роль passkey играет в аутентификации. Это не косметика, от этого зависит всё: код, UX и то, что ломается.

Подход A — passkey как второй фактор. Базовый слой — пароль, а WebAuthn-ключ (аппаратный или платформенный, TouchID/Windows Hello) подтверждает вход сверху. Это семейство Two Factor (WordPress-официальный) + к нему провайдер WebAuthn. Логин выглядит как пароль → «подтвердите ключом». Плюс: мягкая миграция, пароль остаётся fallback. Минус: это не «беспарольный вход», это усиленный парольный — вы по-прежнему уязвимы к фишингу пароля на шаге 1 (см. тезис первой статьи: passkey структурно анти-фишинговый, но только когда он и есть аутентификатор, а не дополнение).

Подход B — passkey как основной способ входа. Самостоятельный плагин (например WP-WebAuthn) ведёт всю церемонию: пользователь вообще не вводит пароль, а «расбирается» с аутентификатором. Иногда с режимом usernameless — логин без даже имени пользователя, по одному biometric-промпту. Плюс: настоящий беспарольный UX и реальная фишинг-устойчивость. Минус: жёстче требования к окружению и к recovery (потерял устройство — как войти? — это тема пятой статьи).

Подход A: passkey = 2FAПодход B: passkey = основной вход
Эталонный стекTwo Factor + WebAuthn Providerсамостоятельный WP-WebAuthn
Пароль остаётся?да (шаг 1)нет / опционально
Usernamelessнетбывает
Миграциямягкая (пароль — fallback)требует recovery-стратегии
Фишинг-устойчивостьчастичная (парольный шаг фишингуется)структурная

Выбор между A и B — первое решение, и оно зависит от задачи, а не от «какой плагин популярнее». Для админки, где сидят 3 человека и нужен дополнительный барьер, — A. Для массового front-end входа, где вы хотите убрать пароль как вектор атаки, — B (и тогда без плана recovery, который даёт пятая статья, не выходить).

Часть II. Официальный Two Factor: почему «официально» ≠ «есть passkeys»

Ожидание: «Two Factor» — плагин от самого WordPress, значит там всё есть. Реальность на момент написания (v0.17.0, 25.09.2026) иная, и эти три факта стоит знать до установки.

Факт 1 — U2F удалён, WebAuthn не встроен. Из Two Factor убрали legacy-провайдер FIDO U2F в версии 0.16.0 (27.03.2026) — «deprecated and removed due to loss of browser support» (браузеры перестали поддерживать старый U2F API). Сам WebAuthn/passkey в базовый Two Factor не входит: в его FAQ прямо написано — для passkeys и аппаратных ключей ставьте отдельный WebAuthn Provider for Two Factor. То есть «официальный 2FA-плагин» без второго плагина даёт вам TOTP, email-коды и backup-коды, но не passkeys. Это и есть разрыв между ожиданием «официальный ⇒ всё есть» и реальностью.

Факт 2 — провайдер WebAuthn живёт отдельно и требует своей базы. WebAuthn Provider for Two Factor (на момент написания v2.6.2) интегрируется в Two Factor как дополнительный provider через фильтр two_factor_providers, держит свои таблицы (wpdb) и тянет серверную библиотеку madwizard/webauthn. У него своя история безопасности: например, в 2.5.6 исправляли authentication bypass с malformed request, а в 2.6.2 — истечение pending-церемоний через 10 минут и «безопасно показывать сообщения об ошибках plain text». Практический вывод: вы ставите не «одну кнопку», а цепочку из двух активно развивающихся плагинов — и обновлять надо оба синхронно (провайдер прямо указывает совместимость с конкретными версиями WP: «Compatibility with WordPress 6.9.x»).

Факт 3 — из коробки 2FA для всех не принуждается. У Two Factor нет встроенной настройки «обязать всех включить 2FA». Это осознанное ограничение (Known feature request, GitHub issue #255). Каждый пользователь сам включает методы в своём профиле; админ может выключать методы site-wide и править профили других, но «включить обязательно для роли X» — это ваш кастомный код на фильтре two_factor_is_required_for_user (и обход по доверенному IP как раз через него). Значит, если задача «защитить админов 2FA принудительно», один только плагин её не закрывает — нужно немного кода (или другой плагин-принудитель). Хорошая новость: этот фильтр + two_factor_fallback_provider_for_user (для случая, когда провайдер плагина выключили, а у юзеров остались к нему привязанные настройки) — это готовые места расширения, не хаки.

Отдельно полезна свежедобавленная вещь: WP-CLI-namespace wp two-factor (v0.17.0). wp two-factor disable --yes <user> — это ваш способ разблокировать залоченного админа из консоли, если он сам не может пройти второй фактор, и вы не хотите лезть в БД руками. Держите этот путь заранее (пятая статья про recovery разовьёт).

Часть III. Настоящий барьер — хостинг, а не безопасность

Самый неочевидный пункт и самый частый источник «у меня не работает». Не «безопасно ли это», а «пускать ли это ваш сервер вообще». Три вещи из инфраструктуры, которые ломают passkeys на дешёвом хостинге:

1. HTTPS — не рекомендация, а условие запуска. WebAuthn работает только в secure-контексте: https:// или localhost. Если сайт на HTTP или с недопиленным сертификатом — церемония navigator.credentials.* в браузере просто не стартует. Это ровно та же линия, что в статье про шифрование и HTTPS, только здесь цена ошибки — «кнопка не нажимается». Проверяется, кстати, вашим же инструментом Проверка SSL-сертификата: убедитесь, что цепочка полная и без mixed-content, прежде чем вообще гадать, «виноват ли плагин».

2. PHP-расширения: gmp и mbstring. WP-WebAuthn в описании прямо требует расширения gmp (для арифметики больших чисел в криптографии) и mbstring. На shared-хостинге gmp часто не включён — и тогда плагин падает («plugin could not work → check whether you have installed the gmp extension»). Проверить можно одной строкой (адрес и пути условные):

PHP
<?php
// quick pre-check перед установкой passkeys-плагина на вашем сервере.
$need = ['gmp', 'mbstring', 'openssl']; // openssl нужен для crypto-операций
foreach ($need as $ext) {
    printf("%-10s %s\n", $ext, extension_loaded($ext) ? 'OK' : 'НЕ ХВАТАЕТ');
}
// secure-context условие — не PHP, а сервер: убедитесь, что сайт на HTTPS.
printf("is_ssl()  %s\n", !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'да' : 'НЕТ');

Если gmp помечен «НЕ ХВАТАЕТ» — это не баг плагина, это ваш хостинг; включайте расширение в панели или меняйте тариф (см. PHP-FPM под WordPress — где вообще живут расширения и настройки).

3. CPU: верификация подписи WebAuthn — дорогая. Это ключевой «не скажут вам при установке» момент. Когда браузер вернул ответ аутентификатора, сервер должен проверить криптографическую подпись — это асимметричная операция (эллиптическая кривая), и в PHP она CPU-intensive. На shared-хостинге с троттлингом CPU по аккаунту это превращается в «логин тормозит» или в срабатывание лимитов именно в момент аутентификации. Практически: на слабом тарифе вы можете получить работающий на desk-top тесте, но задыхающийся на проде вход. Это не «починить плагином», это либо сменить тариф, либо держать heavy-crypto на нормальном VPS (первая статья серии про анатомию VPS — про то, почему свой сервер снимает эти лимиты).

Бонус: challenge протухает. WebAuthn-церемония живёт секунды-минуты: сервер генерирует одноразовый nonce (challenge), пользователь должен подтвердить ключом, и nonce истекает. WebAuthn Provider for Two Factor в 2.6.2 явно закрывает 10-минутное окно pending-регистраций/входов и перезапускает церемонию при истечении. Держите это в UX: пользователь, «зависший» на подтверждении, должен получать внятный «истекло, начать заново», а не молча тупик. (Сам механизм challenge-response разбирает первая статья.)

Часть IV. WooCommerce: боль не в логине, а в чекауте

В WooCommerce «passkeys» — это не только страница /my-account/. Живой пропускной узел — оформление заказа: гостевой или залогиненный покупатель на чекауте, и тут есть специфика.

Checkout живёт в двух местах сразу, и это ловушка. У WooCommerce два чекаута: классический (PHP-шаблоны) и блочный (Block Checkout). Для passkey-интеграции браузерный API один и тот же (navigator.credentials.* — ему всё равно, где форма), но прикрутить форму/JS к странице надо по-разному: классика цепляется через хук вроде woocommerce_checkout_before_order_review, блочный чекаут — через свой хук блока. Отсюда типичный баг «работало на старом чекауте, сломалось после перехода на blocks». Проверять надо конкретный активный путь оформления, а не «в целом чекаут».

Готовность решения — «в целом да, но тестируйте весь customer-flow». Оценка экосистемы на 2026 («WordPress Passkeys: Is Passwordless Login Ready for WooCommerce in 2026»): WebAuthn и поддержка браузеров/устройств достаточно зрелые, что большинство WP-плагинов закрывают сложность; но после внедрения обязательно прогнать сквозной сценарий — регистрация → вход → смена устройства → чекаут с passkey → recovery. Отдельно есть профильный «Biometric Passkey Login» для WooCommerce — всё, что он делает с таблицами, это CRUD ключей; сама крипто-церемония возможна только в браузере, сервер её за пользователя не выполнит. Не ждите, что «плагин на сервере» авторизует вместо клиента.

Отдельный вопрос:guest-чекаут и аккаунты. Беспарольный вход покупательского аккаунта упирается в то же, во что и фронтенд-вход вообще — в recovery. Если покупатель создал аккаунт с passkey и сменил телефон, а вы выключили пароль как fallback, — это потерянный заказ и тикет в поддержку. Пятая статьи серии именно про это (стратегия миграции без потери аккаунтов); в WooCommerce цена ошибки выше, чем в админке, потому что пользователей тысячи, а поддержка у них — форма, а не SSH.

Часть V. Как выбрать: модель доверия × готовность тестировать

Соберём критерии выбора, а не «рейтинг». Вопрос не «какой плагин лучше», а «какой соответствует вашей модели угроз и вашему хостингу».

Начните с вопроса: passkey — второй фактор или замена пароля?

  • Нужен дополнительный барьер для админов/ограниченной группы, с мягким откатом на пароль → Подход A (Two Factor + WebAuthn Provider). Дешевле по внедрению, пароль остаётся safety net, но и фишинг пароля остаётся возможен.
  • Хотите убрать пароль как поверхность атаки для массового входа → Подход B (WP-WebAuthn и аналоги, возможно usernameless). Мощнее по безопасности, но обязателен план recovery (статья 5), иначе теряете аккаунты.

Транспортируйте список требований на конкретный плагин (переснимайте по карточке в день установки!):

  1. Требования к PHP/WP-версии (например, провайдер WebAuthn на момент написания просил PHP 8.1 / WP 6.0; WP-WebAuthn поднял минимум до 7.4 и обещал переход на 8.0+ — цифры из changelog, уточняйте актуальные).
  2. Нужны ли gmp/mbstring (да для WP-WebAuthn; у провайдера heavy-crypto тоже через madwizard/webauthn).
  3. Поддержка multisite (у WP-WebAuthn — beta; у Two Factor — есть, но без network-wide принуждения).
  4. История безопасности (совпадение с OWASP A07 «Identification and Authentication Failures»): были ли recent auth-bypass фиксы, как скоро релизились.
  5. Наличие WP-CLI / путей разблокировки залоченного (см. wp two-factor disable).
  6. Совместимость форм-факторов: TOTP + passkey + backup-коды одновременно (это и есть «без потери аккаунта» в миниатюре).

И общий тест готовности. Если у вас shared-хостинг без gmp, без нормального HTTPS и с жёстким CPU-лимитом — правильный порядок действий: сначала чинить инфраструктуру (Расширение → HTTPS → тариф), а уже потом ставить passkeys. Обратный порядок даёт «плагин установлен, не работает, автор плагинов не при чём» — самый дорогой тип дебага.


Инструменты под задачу

Перед установкой любого passkeys-плагина полезно быстро прогнать инфраструктурную часть: проверить, что HTTPS-цепочка полная и без mixed-content (Проверка SSL-сертификата), посмотреть, что реально отдаёт сервер на endpoints церемонии (Проверка HTTP-заголовков), и если нужна помощь с кодом ceremony-эндпоинта — разбор фрагмента PHP через чат-ассистента: https://codestack.space/ai-pomoshhnik-dlja-koda/


Чек-лист граблей

  • Ждёте, что Two Factor «официальный ⇒ passkeys внутри». U2F удалён (0.16.0), WebAuthn — отдельный провайдер; базовый плагин даёт TOTP/email/backup, не passkeys.
  • Ставите только Two Factor и удивляетесь отсутствию ключа. Нужна цепочка из двух активно развивающихся плагинов; обновлять синхронно, сверять совместимость версий WP/PHP.
  • Считаете, что 2FA принудится из коробки. У Two Factor нет built-in enforcement (issue #255); нужен кастомный код на two_factor_is_required_for_user.
  • Игнорируете HTTPS. WebAuthn молча не стартует на HTTP/mixed-content — сначала SSL, потом гадать про плагин.
  • Хостинг без gmp/mbstring. Плагин не «ломается сам» — не хватает расширения; проверяйте extension_loaded() до установки.
  • Забываете про троттлинг CPU. Верификация подписи — дорогая асимметричная крипто на PHP; shared-тариф задыхается именно на аутентификации.
  • Не закладываете expire challenge. Pending-церемония живёт минуты (10 мин в провайдере); без внятного «истекло, начать заново» — тихий тупик.
  • Тестируете только /my-account/ в WooCommerce. Реальный узел — checkout; классический и блочный — разные хуки, форма прикручивается дважды.
  • Ждёте, что серверный плагин «авторизует вместо клиента». Крипто-церемония возможна только в браузере; сервер делает CRUD ключей и верификацию, но не нажимает кнопку за пользователя.
  • Спутали Подход A и B. «passkey = второй фактор» и «passkey = замена пароля» — разная модель доверия, разный код и (для B) обязательный recovery-план.
  • Перевели всех на passwordless без recovery. Сломается на первом же сменённом телефоне; в WooCommerce это потерянные заказы и тикеты.
  • Доверяете версиям из статьи как актуальным. Экосистема двигается быстро; переснимайте карточку плагина в день установки.

👤 Зарегистрируйтесь, чтобы добавить материал в закладки.