Per-Role 2FA Enforcement: Require 2FA Without Locking Out Users
Per-Role 2FA Enforcement lets you require two-factor authentication for any selected user role (typically Administrators, sometimes Editors too) without forcing every Subscriber to enroll. GuardPress gives existing users a 7-day grace period with a yellow countdown banner so nobody is suddenly locked out of admin tools. After the grace window expires, unenrolled users in an enforced role are redirected to their profile to set up 2FA before they can continue. This is the runbook for configuring it, what the grace period looks like in practice, and how to recover via wp-config.php if everyone gates themselves out at once.
What Per-Role 2FA Enforcement Does
Per-Role 2FA Enforcement (shipped in GuardPress 1.6.13) is a role-scoped gate on top of the global 2FA module. You pick which roles must have 2FA enrolled, and GuardPress quietly nudges users in those roles to set it up. After a grace window, the nudge becomes a hard redirect — users in an enforced role who haven’t enrolled can’t reach any wp-admin screen until they do.
- Role-based, not user-based. You select roles (Administrator, Editor, Author, custom roles — whatever
wp_roles()returns on your site). Every user in a selected role is subject to enforcement. There’s no per-user override toggle — if you need to exempt one specific user, move them to a role that’s not enforced. - 7-day grace period from the last role-list change. Any change to the enforced-roles list — adding a role, removing one, or replacing the whole list — resets the clock to “now” so newly-enforced users always get the full 7 days to enroll.
- Yellow countdown banner during grace shown on every wp-admin screen, only to users who are actually being gated (not to admins reviewing other people’s profiles). The banner counts down in days remaining and links straight to the 2FA setup section of the profile page.
- Hard redirect after grace. Once the 7-day window elapses, any unenrolled user in an enforced role gets
wp_safe_redirect()’d toprofile.php#guardpress-2fa-setupon every admin page load. They can still enroll from there; they just can’t go anywhere else in wp-admin first. - Escape hatch via
GUARDPRESS_EMERGENCY_BYPASSin wp-config.php. The same constant Emergency Lockdown uses. One constant, both bypasses — intentional, so admins only have one thing to remember when everything goes sideways.
The role-enforcement UI appears only when GuardPress is licensed. The underlying global 2FA toggle (“Enable 2FA for all users”) is available in both editions, but the per-role gate — the role checkbox grid, grace banner, and redirect logic — is part of GuardPress Pro.
Setup Walkthrough
Four steps. About two minutes once you know where the toggle lives.
Enable the global 2FA module
Go to GuardPress → Settings → Login Security. Check “Enable 2FA for all users” and save. This makes 2FA available to enroll on user profile pages — without this, the per-role gate has nothing to gate against.
Pick the roles you want to require 2FA for
Just below the global toggle (Pro-only), you’ll see a “Require 2FA for these roles” checkbox grid showing every role on your site (Administrator, Editor, Author, Contributor, Subscriber, plus any custom roles WooCommerce / MemberPress / your theme have registered). Check the roles you want to enforce. The conservative choice is Administrator only; Administrator + Editor covers content-publishing accounts too.
Save
Save the settings page. The moment the role list changes, GuardPress writes the current timestamp to the guardpress_2fa_enforcement_started_at option — that’s the start of the 7-day grace window. A green / amber status line appears below the role grid: “Grace period: 7 days remaining before unenrolled users in these roles are gated.”
Tell your team
This is the single biggest pitfall. The countdown banner is loud, but if an Editor only logs in once a week they might miss it entirely. Send a heads-up: “We’re requiring 2FA for Administrators and Editors. You have until [date]. Set it up at Users → Profile → GuardPress Two-Factor Authentication.”
What Happens During the 7-Day Grace Window
For every user in an enforced role who hasn’t enrolled 2FA yet:
- Yellow admin notice on every wp-admin page. Headline: “Two-factor authentication will be required for your account soon.” Body: “You have N day(s) to enroll before access to admin tools is restricted.” Followed by a Set up 2FA now link that drops them at
profile.php#guardpress-2fa-setup. - Day counter ticks down. The banner uses
(int) ceil()over the seconds remaining, so “1 day remaining” means somewhere between 1 second and 24 hours. Plan around the conservative end. - No redirect yet. Users can keep using wp-admin normally during grace. The redirect doesn’t fire until the grace timestamp + 7 days has fully elapsed.
- Banner suppresses itself for users who don’t need it. Already enrolled? No banner. Not in an enforced role? No banner. Reviewing another user’s profile? No banner (you’d see a misleading “you must enroll” about a different user).
Changing the enforced-roles list at any time — adding a role, removing one, swapping the whole list — resets the 7-day clock to that moment. This means if you add Editor to an existing “Administrator” enforcement on day 4, both Editors and any new Administrators get a fresh 7 days from the change. The existing Administrators who were already in grace get a fresh window too — the option-update handler doesn’t distinguish which role added a user. If you want a tighter window, change the list closer to your hard cutover date.
What Happens After the Grace Window Expires
Once 7 days have passed since the last enforced-roles change:
- Yellow countdown banner disappears. A green status line replaces it in GuardPress → Settings → Login Security: “Enforcement is active. Unenrolled users in these roles are being redirected to enroll on their profile.”
- Unenrolled users in enforced roles are redirected on every wp-admin page load. They land at
profile.php#guardpress-2fa-setup. They can scroll the page, set up their authenticator app, scan the QR, and finish enrollment — the redirect specifically allows the profile page and the AJAX endpoints (gp_generate_2fa_secret,gp_verify_2fa_setup) the setup flow uses, so enrollment isn’t broken by its own gate. - The redirect fires at
admin_initpriority 999, which means it runs after most plugin admin code but before page render. Any custom dashboard widgets or admin notices from other plugins won’t render for the gated user — they never reach those screens. - Logout still works.
wp-login.php?action=logoutdoesn’t pass throughadmin_init, so logged-in users can still sign out normally even when gated. - Front-end browsing is unaffected. The gate only runs on
admin_init— logged-in users in enforced roles can still visit the front of the site, view pages, comment, etc. They just can’t reach wp-admin.
Users who enroll after the gate has kicked in just complete the setup wizard, save, and the next admin-page request goes through normally. No grace re-issue, no admin action required.
Locked Yourself Out? Use the wp-config Bypass
The worst case: enforcement was added to a role that turned out to include the only admin who could disable it, that admin’s authenticator phone died / got wiped / fell in the toilet, and now everyone with the “turn 2FA enforcement off” capability is stuck on the profile page. The bypass is the same constant Emergency Lockdown uses — reused intentionally so there is exactly one wp-config constant to remember.
You need to edit wp-config.php in the WordPress root directory. There’s deliberately no in-browser bypass — that would be a permanent backdoor an attacker could exploit through compromised admin credentials.
Connect via FTP, SSH, or your host’s file manager
Navigate to the WordPress root directory (the one containing wp-login.php, wp-config.php, and the wp-content/ folder).
Open wp-config.php for editing
Find the line that reads /* That’s all, stop editing! Happy publishing. */ — this is the canonical insertion point for custom constants in WordPress.
Add the bypass constant ABOVE that line
Paste this exactly:
define( 'GUARDPRESS_EMERGENCY_BYPASS', true );Save the file. The 2FA enforcement gate checks this constant first and short-circuits before any redirect logic runs — every user can reach wp-admin again, enrolled or not.
Sign in and either disable enforcement or enroll
Go to GuardPress → Settings → Login Security. You have two choices:
- Uncheck the enforced roles entirely — turns enforcement off site-wide. Save.
- Or have every affected user enroll 2FA right now from Users → Profile → GuardPress Two-Factor Authentication. Once they’re all enrolled, you can leave enforcement on.
Remove the bypass constant from wp-config.php
Go back to FTP / SSH / file manager and delete the define( 'GUARDPRESS_EMERGENCY_BYPASS', true ); line you added. Save. Leaving it in is harmless when neither enforcement nor Emergency Lockdown is active (it’s a no-op), but it means a future incident has no working gate — always remove after recovering.
Common Mistakes
Enforcing on Subscriber or WooCommerce Customer roles
Customer / subscriber roles often have hundreds or thousands of users, and most of them don’t use wp-admin at all — they shop, log in to /my-account/, log out. Enforcing 2FA on those roles either generates thousands of grace banners nobody acts on, or after day 8 starts redirecting every shopper trying to view their account to a profile setup page they didn’t ask for. Enforce on staff roles (Administrator, Editor, Author) — not on customer roles.
Not telling co-admins before saving the role list
The grace banner is on every wp-admin screen, but if an Editor logs in once a fortnight they won’t see it before the 7-day window closes. Send a calendar invite or a Slack message with the deadline and a one-line how-to: “Profile → GuardPress Two-Factor Authentication → scan QR with your authenticator app → enter the code → save.”
Multi-admin sites where one admin hasn’t enrolled
If you have two admins and only one has 2FA set up, enforcing on Administrator after the 7-day window will lock out the un-enrolled one. They’ll keep getting redirected to the profile page — which is fine; they can enroll from there — but they can’t do anything else until they do. Verify every admin has enrolled 2FA before the deadline.
Custom roles you forgot exist
WooCommerce registers shop_manager and customer; MemberPress / LearnDash / BuddyPress add more; some themes register their own. The role grid lists everything wp_roles()->roles returns on your site — review the whole list before saving so you don’t enforce on a role you didn’t mean to.
Treating the redirect as a bug
After the grace window expires, a user in an enforced role who hasn’t enrolled will be redirected to the profile page every time they hit wp-admin — even from the Dashboard “Howdy” menu, even after clicking a deep wp-admin link in an email. This is the gate working as designed. Either complete enrollment, or unmark that role from enforcement.
Edge Cases
WooCommerce Customer / Shop Manager
The role grid will include shop_manager (which usually should have 2FA — they can access orders and customer data) and customer (which usually should not — see “Common Mistakes” above). Treat Shop Manager like Editor; leave Customer alone.
Users with multiple roles
WordPress users can have more than one role. The enforcement gate fires if any of a user’s roles is in the enforced list — the check is array_intersect( $user_roles, $enforced_roles ). A user with both administrator and customer is gated as soon as Administrator is enforced.
Custom roles registered by plugins / themes
Custom roles appear in the grid by their registered name. The enforcement logic is role-key-based, so renaming or re-registering a role at the same key keeps enforcement applied. Deleting a custom role removes it from the grid; if it was in the enforced list, it’s silently dropped from enforcement on the next page render.
Super-admins on multisite
On a multisite network, administrator is per-site. A Network Admin who isn’t also a regular Administrator on the site won’t be gated by site-level enforcement — their role intersection on that site returns empty. If you need network-wide enforcement, configure it on each site, or escalate to a site-level Administrator role first.
Users who already had 2FA enrolled before enforcement was turned on
They’re fine. The gate’s very first check after the role membership test is is_user_2fa_enabled( $user->ID ) — already enrolled = nothing to do. The grace banner also suppresses for them.
FAQ
Can I shorten the 7-day grace period?
Not from the UI. The 7-day window is hard-coded as 7 * DAY_IN_SECONDS in the grace-period helper. If you genuinely need a tighter window (e.g. you’re responding to a security incident and want to flip enforcement on immediately), the cleanest path is: enable enforcement, then have every affected user enroll right now while the banner is still showing. The redirect doesn’t fire until day 8 anyway — the grace window is the worst case, not a forced wait.
Can I exempt a single user from enforcement?
Not via a per-user override. The gate is role-scoped, not user-scoped — intentionally, to keep the model simple. If you need to exempt one user temporarily, change them to a role that’s not enforced (Editor → Author, for example), have them keep doing their work, and put them back later. The cleaner long-term answer is “they should enroll 2FA” — the whole point of the feature is no exceptions on critical accounts.
Does enforcement work without the global 2FA toggle on?
No. The global “Enable 2FA for all users” toggle has to be on for the 2FA module’s setup UI and verification hooks to register. If it’s off, the per-role enforcement gate technically still runs (the option-change listener registers regardless), but users redirected to the profile page won’t see the 2FA setup section — they have nowhere to enroll. Always enable the global toggle first.
What about Application Passwords / REST API?
Application Passwords are intentionally exempt from 2FA — a bearer token is the second factor. GuardPress disables Application Password creation for users who have 2FA enabled (via the wp_is_application_passwords_available_for_user filter), but the per-role enforcement gate only runs on admin_init, so Application Password REST requests aren’t blocked by it. If a user has Application Passwords but hasn’t enrolled the interactive 2FA flow, they can still authenticate to the REST API — they just can’t reach wp-admin in a browser.
What if my authenticator app stops working?
Standard 2FA recovery applies — GuardPress 2FA supports backup codes (regenerable via the gp_regenerate_backup_codes AJAX action on the profile page). If you’ve lost both the authenticator and the backup codes, your options are: (1) another admin disables 2FA for your account from Users → [your account] → GuardPress 2FA section, or (2) wp-config bypass above + reset your own 2FA from the profile page. See the related Locked Out Recovery and 2FA Recovery articles below.
Still Stuck? Email Priority Support
If enforcement isn’t behaving the way this article describes, or you’re hitting an edge case the FAQ doesn’t cover:
Email support@royalplugins.com with the diagnostic info below. Priority email support is included with your GuardPress Pro license — typical response time is within 24 hours.
Information to include in your email
- GuardPress version from WP Admin → Plugins (must be 1.6.13 or higher — per-role enforcement shipped in 1.6.13)
- WordPress version from WP Admin → Updates
- Which roles you’ve enforced — copy the role keys from the checkbox grid
- When you enabled enforcement — approximate is fine; we’ll cross-reference against the
guardpress_2fa_enforcement_started_atoption - What you expected to happen vs. what actually happened — e.g. “Editor user X has 2FA enrolled but is still being redirected”
- Whether you have FTP / SSH / file manager access — if you’re asking about a lockout, we’ll need to confirm the bypass route is available to you
If your 2FA problem isn’t enforcement-related:
- Emergency Lockdown Recovery — the site-wide login kill switch and how to recover via the same wp-config bypass constant
- 2FA Recovery — what to do if you’ve lost your authenticator and backup codes
- Locked Out Recovery — broader lockout recovery covering brute-force, IP blocks, and the custom login URL
- Cloudflare Turnstile Setup — pair 2FA with a stronger CAPTCHA to harden the wp-login.php surface