-
Notifications
You must be signed in to change notification settings - Fork 159
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Trigger two-factor flow only when expected #660
base: master
Are you sure you want to change the base?
Changes from 5 commits
8aef3df
0e1b244
e7f1ad6
7a3d5ed
0de50df
76192e6
4eafeed
315cf26
4c2345b
2a713ea
b9c200d
7cb84f5
cf0852b
2dd1c2f
89b6829
a096066
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -94,7 +94,6 @@ class Two_Factor_Core { | |
*/ | ||
public static function add_hooks( $compat ) { | ||
add_action( 'init', array( __CLASS__, 'get_providers' ) ); // @phpstan-ignore return.void | ||
add_action( 'wp_login', array( __CLASS__, 'wp_login' ), 10, 2 ); | ||
add_filter( 'wp_login_errors', array( __CLASS__, 'maybe_show_reset_password_notice' ) ); | ||
add_action( 'after_password_reset', array( __CLASS__, 'clear_password_reset_notice' ) ); | ||
add_action( 'login_form_validate_2fa', array( __CLASS__, 'login_form_validate_2fa' ) ); | ||
|
@@ -117,8 +116,13 @@ public static function add_hooks( $compat ) { | |
add_action( 'set_auth_cookie', array( __CLASS__, 'collect_auth_cookie_tokens' ) ); | ||
add_action( 'set_logged_in_cookie', array( __CLASS__, 'collect_auth_cookie_tokens' ) ); | ||
|
||
// Run only after the core wp_authenticate_username_password() check. | ||
add_filter( 'authenticate', array( __CLASS__, 'filter_authenticate' ), 50 ); | ||
/** | ||
* Enable the two-factor workflow only for login requests with username | ||
* and without an existing user cookie. | ||
* | ||
* Run after core username/password and cookie checks. | ||
*/ | ||
add_filter( 'authenticate', array( __CLASS__, 'filter_authenticate' ), 31, 3 ); | ||
|
||
// Run as late as possible to prevent other plugins from unintentionally bypassing. | ||
add_filter( 'authenticate', array( __CLASS__, 'filter_authenticate_block_cookies' ), PHP_INT_MAX ); | ||
|
@@ -676,18 +680,26 @@ public static function destroy_current_session_for_user( $user ) { | |
* Prevent login through XML-RPC and REST API for users with at least one | ||
* two-factor method enabled. | ||
* | ||
* @param WP_User|WP_Error $user Valid WP_User only if the previous filters | ||
* @param WP_User|WP_Error $user Valid WP_User only if the previous filters | ||
* have verified and confirmed the | ||
* authentication credentials. | ||
* @param string $username The username. | ||
* @param string $password The password. | ||
* | ||
* @return WP_User|WP_Error | ||
*/ | ||
public static function filter_authenticate( $user ) { | ||
if ( $user instanceof WP_User && self::is_api_request() && self::is_user_using_two_factor( $user->ID ) && ! self::is_user_api_login_enabled( $user->ID ) ) { | ||
return new WP_Error( | ||
'invalid_application_credentials', | ||
__( 'Error: API login for user disabled.', 'two-factor' ) | ||
); | ||
public static function filter_authenticate( $user, $username, $password ) { | ||
if ( ! empty( $username ) && $user instanceof WP_User && self::is_user_using_two_factor( $user->ID ) ) { | ||
// Disable authentication requests for API requests for users with two-factor enabled. | ||
if ( self::is_api_request() && ! self::is_user_api_login_enabled( $user->ID ) ) { | ||
return new WP_Error( | ||
'invalid_application_credentials', | ||
__( 'Error: API login for user disabled.', 'two-factor' ) | ||
); | ||
} | ||
|
||
// Trigger the second-factor flow for valid users. | ||
add_action( 'wp_login', array( __CLASS__, 'wp_login' ), PHP_INT_MAX, 2 ); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Another major difference here is that we're now triggering the The only risk here is that some other plugin hijacks the login flow before us and issues a redirect, for example. I add this sample hook: add_action(
'wp_login',
function ( $user ) {
if ( $user ) {
wp_redirect( admin_url( '?redirect=test' ) );
exit;
}
}
); which returns a redirect before our |
||
} | ||
|
||
return $user; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Priority 31 is still after
wp_authenticate_username_password()
so the resolved$user
will be set correctly.