Skip to main contentSkip to footer
Plugin Guides

WordPress Two-Factor Authentication With App, Passkey or YubiKey

Updated Patrick Schlesinger
ReportedIP Hive plugin guide cover, four-method WordPress two-factor authentication

WordPress two-factor authentication is usually sold as an add-on or a premium tier. ReportedIP Hive ships four 2FA methods in the core, authenticator app, passkey or hardware security key, email code and SMS, with TOTP, passkey and email free on every plan.

Since Hive 2.1.36 (5 August 2026) a hardware security key such as a YubiKey is officially supported and works on all three challenge surfaces: the wp-login interstitial, the WooCommerce storefront and the lost-password gate.

This guide covers all four methods, how to enrol a YubiKey step by step, how the rate-limit ladder stops code-guessing, and the reset-flow gap most 2FA plugins leave open.

What is ReportedIP Hive?

ReportedIP Hive is a complete WordPress security plugin: 18 attack sensors, the full 2FA suite described here, progressive blocking and opt-in community threat intelligence. The detection and identity core is GPL-2.0 and works offline. The full ReportedIP Hive feature set is on the product hub.

The four methods in the core

  • Authenticator app (TOTP): RFC 6238 codes, compatible with Google Authenticator, Authy, 1Password and Microsoft Authenticator. Secrets are encrypted at rest. Free on every plan.
  • Passkey and security key (WebAuthn / FIDO2): Face ID, Touch ID, Windows Hello and hardware keys such as the YubiKey 5 series. Phishing-resistant, with an in-house implementation and no Composer dependency. One key per account is free on every plan.
  • Email code, a 6-digit code valid for 10 minutes, rate-limited to 3 sends per 15 minutes with a 60-second resend cooldown and 5 verify attempts per code. The login screen no longer auto-sends it; the user presses Send code first. Free on every plan.
  • SMS code, delivered through the managed reportedip.com relay on Professional plans and up. Numbers are validated as E.164 and sent worldwide; the relay answers with a typed country_not_supported error for the few destinations it does not serve. Phone numbers are encrypted at rest.

Backing all four: 10 single-use recovery codes (hashed at rest, with a low-codes warning at 3 remaining), trusted devices with a configurable expiry (default 30 days), and role-based enforcement with a grace period (default 7 days) and a skip counter. Users pick which method the login challenge asks for first with Make default on any active method.

How to set up a hardware security key

A hardware key is the one second factor that cannot be phished, relayed or read off a screen: WebAuthn binds the credential to the site origin, so the key refuses to sign for a look-alike domain. Hive 2.1.36 made that path official on real hardware rather than just in a browser’s virtual authenticator.

Which keys work

  • YubiKey 5 series: USB-A, USB-C and Lightning, including the NFC models you tap against a phone.
  • Security Key by Yubico and other FIDO2/CTAP2 authenticators.
  • Platform passkeys: Face ID, Touch ID and Windows Hello, enrolled through the same flow.
  • Not supported: older U2F-only keys that speak CTAP1 and nothing newer.

Ed25519 (EdDSA, COSE algorithm -8) is on the list of offered algorithms, but only when libsodium is present server-side to verify it, a key registered today would be dead weight tomorrow if the server could not check its signatures. That matters because Ed25519 is what YubiKey firmware 5.2.3 and later prefers. ES256 (-7) on P-256 and RS256 (-257) stay the fallbacks, with the curve checked explicitly on the COSE EC2 path.

The verifier is written in-house: a self-contained WebAuthn Level 2 implementation with its own CBOR decoder and COSE-to-PEM conversion, verifying signatures through OpenSSL and, for Ed25519, libsodium. The plugin’s only runtime Composer dependency is its update checker, so the code handling your login sits in the source you can read on GitHub rather than in a vendored library.

Enrolling the key takes four steps

  1. Serve the site over HTTPS. WebAuthn only runs in a secure context, so a plain-HTTP staging site will not show the dialog at all.
  2. Open your WordPress profile in wp-admin and find the two-factor section, the security-key manager lives there, not in the front-end dashboard. The setup wizard offers the same flow during onboarding.
  3. Choose Security key (USB / NFC) rather than This device. The first sends authenticatorAttachment: cross-platform, the second platform, so Chrome and Edge open the right dialog directly instead of first offering Windows Hello.
  4. Name the key, “YubiKey office”, “backup key in the safe”, up to 64 characters, then touch it or tap it against the phone. The ceremony window is 120 seconds instead of the WebAuthn default of 60, which leaves time for an NFC tap.

A fresh key will not ask for a FIDO2 PIN. Registration requests userVerification: discouraged, following Yubico’s developer guidance for a key used as a second factor behind a password; the value is enforced server-side as well and can be raised to preferred or required through the reportedip_hive_webauthn_user_verification filter. Registration also asks for residentKey: discouraged, so enrolling a YubiKey does not burn one of its limited discoverable-credential slots, the login flow always supplies allowCredentials, so a discoverable credential would buy nothing here. Credentials created before that change keep working.

Registering the same key twice is refused by the browser through excludeCredentials, and the options endpoint is throttled to 10 requests per user per 10 minutes.

Where the key works after enrolment

All three challenge surfaces render the same shared WebAuthn panel and can complete a full ceremony: the wp-login interstitial, the WooCommerce storefront challenge (Professional) and the password-reset gate. Both of the latter two were broken before 2.1.36, the storefront rendered a passkey tab whose panel did not exist, and the reset gate offered WebAuthn but loaded no ceremony script.

Clone detection is armed by default

Every assertion carries a signature counter. If the counter does not advance, Hive rejects the sign-in, logs a 2fa_webauthn_counter_regression event at severity high and emails the account owner, a counter that stands still is the tell-tale of a credential copied out of its hardware. Counter-less platform passkeys, which legitimately report zero, keep working. That warning mail reaches every plan, not just Business.

Around it sit the ordinary ceremony checks: challenges are 32 random bytes, single-use and valid for 300 seconds; assertions and registrations without the user-presence flag are rejected as required by WebAuthn section 7.2; and the WebAuthn login endpoints sit behind the same per-IP lockout ladder as the code form, so they cannot be used to sidestep the rate limit.

One key is free, a backup key is a Business feature

One security key or passkey per account is free on every plan, including enrolment, login on all three surfaces, renaming, deletion and the cloned-key warning mail. The Business plan adds Advanced Security Keys: several keys per account so one can live in a safe as a backup, automatic model detection, and mails for key-lifecycle events. Model detection requests a direct attestation, reads the AAGUID and matches it against a bundled registry of 90 authenticator models taken from the FIDO Alliance Metadata Service, so the key manager labels an entry “YubiKey 5 Series with NFC” or “Windows Hello” under its name.

That label is display-only and fails open: an attestation that is missing or cannot be verified never blocks a registration, and no attestation CA chain is validated. For a second factor enrolled after a successful password login, attestation adds no meaningful assurance, it is there to tell two keys apart in a list. Free-plan registrations request attestation: 'none', so the browser shows no consent prompt for a feature the plan does not include.

If you stay on the free plan with a single key, your recovery codes are the backup. Print them, or keep an authenticator app as a second method. Hive will not let you delete your last key while WebAuthn is your only active method and 2FA is enforced for your role.

The rate-limit ladder stops code-guessing

Wrong 2FA codes share the same multi-stage ladder as failed logins: 3 wrong codes → 30 s, 5 → 5 min, 10 → 30 min, 15 → 1 h. The 15th IP-level failure graduates the IP to a real progressive block, so a brute-forcer can no longer just time out and retry every hour.

The password-reset gate most plugins miss

WordPress’s “lost password” flow is a classic 2FA bypass: if your only second factor is email, anyone with mailbox access gets both the reset link and the code on the same channel. Hive’s reset gate demands a non-email second factor, authenticator app, SMS, security key or recovery code, before a new password is accepted. Email is excluded by design. The behaviour aligns with NIST SP 800-63B §6.1.2.3 and OWASP ASVS V6.3.

The gate checks each eligible method for usability before it renders, a TOTP secret that will not decrypt, a missing phone number or an absent WebAuthn provider drops that method from the picker. If none is usable the flow hard-stops with an admin mail listing what is broken instead of dropping the user into an “invalid code” loop. Accounts whose only factor is email and which hold no recovery codes are locked out of the reset flow with an admin alert; an administrator clears that with wp user reset-password <id> --skip-email. During a security-key reset the browser is bound to the reset identity by a short-lived, server-minted token rather than a URL parameter.

How to enable it

In the setup wizard’s 2FA step (or Settings → Two-Factor), enable the methods you want to offer, choose which roles must enrol, and set the grace period and skip counter. Fresh installs allow all four methods by default, with SMS becoming usable once a relay-capable plan is connected.

For headless or custom flows, the reportedip-hive/v1 REST namespace exposes /2fa/challenge, /2fa/verify and /2fa/methods for the code-based methods. WebAuthn is deliberately absent there: a browser ceremony needs the admin-ajax surface it already runs on, and duplicating it in REST would mean two code paths to keep in sync on a security-critical flow.

Shell admins can run wp reportedip 2fa reset <user> to clear a locked account. wp reportedip 2fa enable <user> --method=webauthn refuses to flag the method for someone who has no key registered, that would lock them out, unless you pass --force. Keys themselves are enrolled in the browser only; there is no CLI path to register one. On subdomain multisite, the reportedip_hive_webauthn_rp_id and reportedip_hive_webauthn_allowed_origins filters set the relying-party ID and the accepted origins.

Questions about hardware keys

Do I still need an authenticator app if I use a YubiKey?

No, a security key alone satisfies every challenge surface and the reset gate. Keep a second method or your recovery codes anyway, because a single key is a single point of failure.

What happens if the key is lost?

Sign in with one of the 10 recovery codes, or with a second key if you are on Business. An administrator can also clear the enrolment with wp reportedip 2fa reset <user>. Delete the lost key from the profile key manager afterwards.

Does a hardware key work on a phone?

Yes, with an NFC-capable key tapped against the back of the phone, the 120-second ceremony window exists for exactly that. USB-C keys work in a phone’s port, and platform passkeys (Face ID, Touch ID) are the alternative if you would rather not carry a key.

Can I sign in with the key alone, without a password?

No. In Hive the key is strictly a second factor: the password is checked first, then the key. That is also why registration does not ask for a discoverable credential. Passwordless sign-in is a different security model, and pretending a second factor is one would be misleading.

Why did my YubiKey type random letters into a field?

Touching a YubiKey outside an active ceremony makes it type its Yubico OTP as if it were a keyboard. Hive recognises that string, clears the field and explains what happened instead of failing with a confusing error.

Related guides

See the authentication documentation for setup detail, browse the full ReportedIP Hive plugin guides, or read the WebAuthn standard at the W3C.

Explore ReportedIP Hive →

Leave a Reply

Your email address will not be published. Required fields are marked *

Fill out this field
Fill out this field
Please enter a valid email address.
You need to agree with the terms to proceed