Add a real second factor with two-factor authentication WordPress logins can enforce by role
Set up two-factor authentication WordPress administrators can require role by role: a TOTP code from an authenticator app, single-use backup codes for a lost phone, and an encrypted secret that never touches a third-party server.
- TOTP codes (RFC 6238) plus 10 single-use backup codes.
- Required per role, so rollout never locks anyone out mid-way.
- AES-256-GCM encrypted secret, backup codes hashed like passwords.
- QR library bundled locally — the secret never reaches a CDN.
Two-factor authentication WordPress: what does the module actually add?
This is what two-factor authentication WordPress sites get with TheOneWP: TOWP_Two_Factor_Auth hooks the authenticate filter to challenge selected roles for a TOTP code after their password is already correct. Setup happens on the user's own profile screen, where a QR code (rendered locally, never via a CDN) and a manual entry key start a standard authenticator app, and the module generates 10 single-use backup codes for when the phone is not available. TheOneWP encrypts the TOTP secret at rest, hashes backup codes like passwords, and lets administrators require the feature role by role without locking out anyone who has not configured it yet.
A single password is one leak away from full access
A WordPress login form built on a password alone gives an attacker exactly one thing to obtain — reused, phished or breached elsewhere — before they are the administrator.
Rolling out a second factor site-wide risks locking people out
Forcing every account to configure a new security step at once, without warning, is how support tickets and locked-out clients happen — the requirement needs a way to reach some roles before others.
A lost phone should not mean a lost account
Any second factor tied to a single device needs a real, verified fallback, not an informal "email us and we'll figure it out" process.
A second factor that rolls out role by role
The module intercepts the login after WordPress core's own check, asks for a TOTP code only from the roles that require it, and gives every account a verified way back in if a device is lost.
Standard TOTP, any authenticator app
A QR code and manual key start Google Authenticator, Authy or any RFC 6238-compatible app — no proprietary app required.
Required per role, not all at once
Check only the roles that must use it; everyone else stays completely unaffected until you select their role.
Ten single-use backup codes
The module generates them at setup and on regeneration, hashes each one, and removes it the moment someone uses it — so a lost phone never means a lost account.
The complete two-factor authentication WordPress feature set
Every capability below is present in the notification-free login flow, the profile-screen renderer or the AJAX purge handlers.
QR code and manual key
The profile screen renders a QR code locally with the bundled QRCode.js and shows the same secret as a manual entry key for apps that cannot scan.
Per-role requirement
A checkbox per registered WordPress role decides which roles the login challenge applies to; matching also honors extra roles from Multi Role Assignment.
Single-use backup codes
The module generates 10 codes in an unambiguous 8-character alphabet (no O/0 or I/1); it shows them once, lets you copy them, and consumes each one on use.
Forced setup redirect
If a user in a required role has not configured 2FA yet, the module redirects every wp-admin request to their profile's setup section until they finish.
Replay-protected TOTP check
Login-time verification records the last accepted time step per user, so nobody can submit an already-used code again.
Guided purge with a real count
Turning off a role or the whole module offers "keep settings" or "delete," and the confirmation dialog first shows exactly how many accounts it would affect.
Roll out two-factor authentication WordPress-wide without locking anyone out
Bring in one role at a time and verify recovery before requiring it more broadly.
Require it for administrators first
Check only the Administrator role to start; every other role stays unaffected until you select its own checkbox.
Set up from the profile screen
Each required user scans the QR code (or enters the manual key) in their own authenticator app and confirms with a 6-digit code.
Save the backup codes immediately
The module shows the 10 generated codes once, so copy and store them somewhere safe before leaving the screen.
Extend to more roles when ready
Check additional roles as they become ready; the module guides anyone not yet configured to setup without locking them out mid-rollout.
Where a second factor matters most
The per-role requirement fits sites where the risk concentrates in a small number of privileged accounts.
Administrator and editor accounts
Require the roles that can change content, plugins or settings, without touching subscriber or customer accounts that carry far less risk.
Agencies managing client logins
Require 2FA for every account with administrator access on a client site, verified with the same encrypted-secret, hashed-backup-code implementation across every project.
Sites handling payments or personal data
Add a real second factor for the roles that can reach order, customer or membership data, alongside the site's other access controls.
A second factor you can roll out safely
Every design choice in the verified code favors a controlled rollout over an all-or-nothing switch.
Assets load only where the page needs them
The verified implementation scopes its scripts and styles tightly instead of loading them site-wide.
Enqueued only on profile screens
The admin stylesheet, the bundled QRCode.js and the setup script load only on profile.php and user-edit.php, and only for a user the module actually applies to.
No third-party script on the login page
The public-facing challenge screen (login_form_towp_2fa) is plain server-rendered HTML — no QR rendering or extra JavaScript needed there.
One filter on the login path
Login-time verification adds a single authenticate filter callback, running only when a user with 2FA enabled has already passed the password check.
Encrypted secrets, hashed codes, replay protection
By design, the module protects every credential it creates: it encrypts secrets, hashes codes, or limits them to a single use.
AES-256-GCM secret encryption
TOWP_FTP_Volume::encrypt() encrypts the TOTP secret before TheOneWP saves it as user meta, and decrypts it only to check a submitted code.
Password-hashed backup codes
wp_hash_password() hashes each backup code — the same one-way hashing WordPress applies to account passwords — so TheOneWP never stores one in plain text.
Replay-protected verification
The module records a per-user "last accepted step" on every successful login code, so nobody can submit the same 30-second code twice.
Password-gated changes to an active setup
Disabling or regenerating codes for one's own account requires re-entering the current password via wp_check_password() before anything changes.
Sits explicitly alongside Access Manager
The supplied code integrates through native WordPress hooks with an explicit execution order relative to other TheOneWP login modules. We make no compatibility claim beyond the verified implementation.
authenticate filter
Registered at priority 40 — after WordPress core's own username/password check (20) and after Access Manager's rate-limit check (30) — so a locked-out or invalid login never reaches the 2FA step.
Multi Role Assignment
The per-role requirement check calls the shared towp_user_roles filter, so it also honors extra roles that Multi Role Assignment grants.
Failed-login and audit hooks
A wrong code fires WordPress core's own wp_login_failed, so Access Manager's lockout counter treats it like a wrong password, and TOWP_Audit_Log records every step.
TheOneWP versus common alternatives
Compare a real two-factor authentication WordPress implementation with typical dedicated 2FA plugins or generic security suites.
| Capability | TheOneWP Two-Factor Auth | Other common solutions |
|---|---|---|
| Rollout control | Required per role, with a forced-but-not-blocking setup redirect | Often all-or-nothing, or requires custom code to stage by role |
| Secret storage | AES-256-GCM encrypted, decrypted only to verify a code | Storage method varies by plugin; not always documented |
| Backup codes | 10 single-use codes, hashed like passwords, shown once | Some plugins omit backup codes entirely, risking lockouts |
| QR rendering | Bundled QRCode.js, secret never sent to a third-party CDN | Often loaded from an external CDN alongside the live secret |
| Replay protection | Last accepted time step tracked per user | Depends on the specific TOTP library used |
| Turning it off | Explicit choice between keeping dormant credentials or deleting them | Disabling often silently deletes stored secrets |
| Administration | One TheOneWP settings panel, nonce-protected purge with a live count | May require a separate plugin or manual database cleanup |
Roll it out without support tickets
A staged rollout and a saved recovery path keep two-factor authentication from becoming a source of lockouts.
Start with Administrator only
Require the highest-privilege role first, confirm the workflow works end to end, then extend to other roles.
Save backup codes the moment they appear
The module shows them once, so use the copy button and store them in a password manager before navigating away.
Choose "keep settings" when in doubt
Deselecting a role or module keeps every secret dormant; only confirm deletion when you are certain nobody needs to recover access to it.
Re-verify after a phone change
A new device means a fresh QR scan. Disable and set up again rather than trying to transfer a secret manually.
Avoid assumptions that cause real lockouts
The module has a defined, verified scope — a few assumptions outside it cause avoidable problems.
Not saving backup codes
The module shows codes exactly once, at generation or regeneration, so closing the screen without saving them removes the only device-independent recovery path.
Requiring every role on day one
Checking every role at once sends every unconfigured user to the setup redirect simultaneously — stage the rollout instead.
Confirming "delete" out of habit
The purge dialog's delete option is irreversible and destroys every secret and backup code for the affected accounts; "keep settings" is the safe default when just pausing the feature.
Two-Factor Authentication FAQ
These answers come directly from the verified class, settings renderer, sanitization rules and AJAX handlers.
What is two-factor authentication WordPress protection with TheOneWP?
It is TOTP-based two-factor authentication: after a correct password, TheOneWP asks selected roles for a 6-digit code from an authenticator app (or a backup code) before the login completes. It hooks the authenticate filter at priority 40, after WordPress core's own check and after Access Manager's rate limiting.
Which roles are actually required to use it?
Only the roles checked in the module settings. A user in a checked role gets the setup section on their profile, and once they configure it, the login challenges them for a code; a user in no checked role never sees the feature at all. The check also honors any extra roles that Multi Role Assignment grants.
What happens if someone in a required role has not set it up yet?
They can still log in with their password. admin_init then redirects every wp-admin request to their profile page's two-factor section until they finish setup, so administrators can make a role mandatory without locking anyone out immediately.
Is the secret key stored securely?
Yes. TOWP_FTP_Volume::encrypt() (AES-256-GCM) encrypts the 160-bit TOTP secret before TheOneWP saves it as user meta, and decrypts it only at the moment a login code needs checking.
Are backup codes stored as plain text?
No. wp_hash_password() hashes each of the 10 generated backup codes, the same one-way hashing WordPress uses for account passwords. TheOneWP checks a submitted code against the hash and, once someone uses it successfully, removes it so nobody can reuse it.
Why does the QR code library ship with the plugin instead of loading from a CDN?
While someone scans it, the setup screen briefly displays the TOTP secret in the clear. A <script src> pulled from an external CDN runs with full access to that page, so the plugin bundles QRCode.js locally instead of trusting a third-party host with that moment.
Can someone reuse an intercepted login code?
No. Login-time verification records the last accepted 30-second time step per user and rejects any step at or before it, so nobody can replay a previously used code even within its normal validity window.
What happens when an administrator turns the whole module off?
A confirmation dialog offers two options: keep the settings, which leaves every secret and backup code saved but inactive, ready for if someone switches the module back on; or delete them, which destroys every stored secret and backup code on the site through the towp_2fa_purge AJAX action, and cannot be undone.
Stop trusting passwords alone.Add a second factor that rolls out safely.
Use two-factor authentication WordPress accounts can rely on: encrypted secrets, hashed backup codes, and a rollout that never locks a role out by accident.

