FactorGuard – Two-Factor Authentication
FactorGuard is a lightweight, privacy-first Two-Factor Authentication (2FA) plugin for WordPress. It adds a rock-solid two-step verification layer to the default WordPress login page, without relying on any external cloud service or third-party API. After a user enters the correct username and passw
FactorGuard is a lightweight, privacy-first Two-Factor Authentication (2FA) plugin for WordPress. It adds a rock-solid two-step verification layer to the default WordPress login page, without relying on any external cloud service or third-party API.
After a user enters the correct username and password, they must complete a second step: enter a one-time code sent to their email or use a time-based code from an authenticator app like Google Authenticator or Authy.
🔒 Zero external API calls. All verification happens on your own server.
Core Features:
- ⚡ Email OTP: send a one-time passcode to the user’s registered email address
- 📱 Authenticator App (TOTP): full RFC 6238 support for Google Authenticator, Authy, and any TOTP-compatible app
- 🔑 One-time backup codes: hashed recovery codes so users never get locked out
- 🔐 Military-grade encryption: TOTP secrets encrypted at rest using libsodium XSalsa20-Poly1305
- 🚫 Replay attack protection: accepted TOTP codes are invalidated for the current time-slice
- ⏱️ Brute force & rate limiting: configurable lockout after too many failed attempts
- 🎛️ Flexible settings: OTP code length (4-10 digits), code expiry (1-60 min), lockout duration
- 🧙 Setup wizard: guided onboarding to configure your preferred 2FA method in minutes
- 🌐 API-safe: automatically bypasses OTP for REST API and XML-RPC requests
- 🌍 Translation ready: fully internationalised and .pot file included
- 🧹 Clean uninstall: removes all plugin data on uninstall (opt-in)
How It Works – Email OTP
- 01User enters their username and password on the login page
- 02If credentials are correct and OTP is enabled, a verification code is emailed to the user
- 03The login form shows an OTP input field (username/password fields are hidden)