Add: Site-wide Two-Factor enforcement per user role - #845
masteradhoc wants to merge 10 commits into
Conversation
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Unlinked AccountsThe following contributors have not linked their GitHub and WordPress.org accounts: @thomasfedb. Contributors, please read how to link your accounts to ensure your work is properly credited in WordPress releases. If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message. To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
There was a problem hiding this comment.
Pull request overview
Adds role-based Two-Factor enforcement to the plugin, allowing admins to mandate 2FA for selected user roles via the settings UI and automatically apply enforcement for existing users (at login) and new users (at registration).
Changes:
- Persist a new
two_factor_enforced_rolesoption and render a role-checkbox “Two-Factor Enforcement” section on the settings page. - Enforce 2FA for users in enforced roles by injecting a provider when the user has none enabled.
- Auto-enable a provider for newly registered users in enforced roles by writing 2FA user meta on
user_register.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 6 comments.
| File | Description |
|---|---|
two-factor.php |
Adds enforcement filter for role-based 2FA and auto-enrollment on registration. |
settings/class-two-factor-settings.php |
Adds settings UI + saves enforced roles option. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
@masteradhoc I would be very keen to roll this out. Is there anything that can be contributed to getting this merged? |
|
Thanks for your comment @thomasfedb. If you could help test this PR and share your feedback that would be amazing and a good step forward! |
@masteradhoc I've now tested this branch properly. Summary: it works as described, and I've sent tests your way.
|
Add tests for role-based Two-Factor enforcement
|
Thank you, @thomasfedb, for your work on testing and writing the unit tests. I’ve merged them. We’re always happy to receive your insights, code contribution and/or testing support on any open PR whenever you have the time. |
|
@masteradhoc any updates on getting this change live? |
|
@thomasfedb Currently part of the team is working on the 7.1 Release. I hope to get more contributors back as soon as the release is fully done :) |
georgestephanis
left a comment
There was a problem hiding this comment.
My only uncertainty is if there's not a workable bypass mechanism for broken outbound mail system or something. Which would probably just be to use wp-cli or phpmyadmin to override the setting or something. So it should be fine?
Intègre les 175 commits accumulés depuis c8c8823 (20/09), dont la release stable 0.17.0 publiée le 28/09 — la première depuis la 0.16.0 du 27/03. Correctif de sécurité déterminant pour ce fork : WordPress#989 empêche un mot de passe classique de contourner la 2FA sur REST et XML-RPC. Notre code testait `did_action( 'application_password_did_authenticate' )`, vrai dès que n'importe quel utilisateur s'était authentifié par application password pendant la requête ; upstream scope désormais la vérification par ID (`$app_password_auth_user_ids`). Les autres correctifs de sécurité de la release (WordPress#877, WordPress#973, WordPress#980) étaient déjà présents ici. Trois PR qui composaient le fork sont maintenant mergées upstream : WordPress#927 (fail-safe), WordPress#917 (rate-limit) et WordPress#882. Notre implémentation locale de WordPress#927 et celle d'upstream sont identiques, d'où l'absence de conflit sur class-two-factor-core.php. Le fork ne repose plus que sur WordPress#845 (enforcement par rôle, approuvée le 24/09 mais non mergée) et WordPress#958. Résolution des trois conflits, upstream retenu dans les trois cas : - tests/class-two-factor-core.php : nos noms de tests contredisaient leurs propres assertions (« invalidates » pour un token vérifié « preserved ») ; upstream les renomme et ajoute test_clear_login_rate_limit. - tests/providers/class-two-factor-email.php : ajout de trois tests de lockout côté upstream, aucun test perdu ici. - readme.txt : notre seul apport propre, la documentation du filtre two_factor_fallback_provider_for_user, est déjà dans leur version. Validation (wp-env, WordPress 7.1 / PHP 7.4) : PHPUnit 308 tests et 932 assertions OK sur les suites single et multisite, dont 10/10 pour le groupe enforcement ; PHPCS 29/29 ; PHPStan 0 erreur ; build OK. Le merge apporte une suite multisite et le support WP-CLI, d'où le passage de 218 à 308 tests et la nouvelle dépendance php-stubs/wp-cli-stubs. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
@georgestephanis do you know when this will go into a release? |
Fixes #846
What?
Adds a Two-Factor Enforcement section to the plugin's settings page that lets administrators require 2FA for specific user roles.
Why?
There is no built-in way to mandate Two-Factor authentication for all users in a given role. Site owners — especially those running membership or multi-user sites — need a way to enforce 2FA for existing users and automatically enroll new users without requiring each user to opt in manually.
See: https://wordpress.org/support/topic/can-i-by-default-turn-on-this-feature-for-all-my-existing-and-for-new-user/ or #307
How?
Three files were changed:
settings/class-two-factor-settings.phptwo_factor_enforced_rolesoption (array of role slugs) alongside the existing provider option.two-factor.php
two_factor_enforce_for_user()— hooked ontwo_factor_enabled_providers_for_userat priority 20. If a user belongs to an enforced role but has no provider configured, the Email provider is injected at runtime so they are challenged on their next login without any manual setup. If the Email provider is disabled site-wide, the function returns unchanged (fails closed) rather than injecting a provider the user has not configured.two_factor_force_on_user_register()— hooked onuser_register. Writes_two_factor_enabled_providersmeta immediately for new users in an enforced role, so enforcement applies from their very first login. Skipped if the Email provider is disabled site-wide.class-two-factor-core.php
uninstall()now also deletestwo_factor_enabled_providersandtwo_factor_enforced_rolesso no orphaned options are left behind when the plugin is removed.Testing Instructions
_two_factor_enabled_providersuser meta is set to["Two_Factor_Email"]immediately after registration.two_factor_enabled_providersnortwo_factor_enforced_rolesremain in the options table.Screenshots or screencast
Changelog Entry