You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When Sign in with Google and the WordPress 2FA plugin are both enabled, creating an account works fine.
But signing in with that account, afterward, reportedly does not work.
This is likely because the 2FA flow fails.
In the case of users whose account uses SiwG, we should likely disable 2FA for that SiwG sign-in flow, relying on the Google Account to use 2FA—this is usually how social logins work 🤔
Steps to reproduce
Set up Site Kit and the Sign in with Google module
Sign out and then try to sign in with that same account again, using Sign in with Google
Do not alter or remove anything below. The following sections will be managed by moderators only.
Acceptance criteria
When the WordPress 2FA plugin is active/detected, users with the existing WordPress accounts and enabled 2FA are prevented from signing in with Google if they don't have their accounts already connected to Google's.
An error is shown to the user stating that their account uses two-factor authentication and that they need to link their account to Google's before they can use Sign in with Google.
Users can connect their Google accounts in their profiles even if they use 2FA. Once accounts are connected, they can sign in with Google.
When a new user is registered using Sign in with Google directly, their new account is connected to Google's automatically as it works today.
Implementation Brief
In includes/Modules/Sign_In_With_Google/Authenticator.php
Add const ERROR_TWO_FACTOR_ENABLED = 'googlesitekit_auth_two_factor_enabled'; with @since.
user_has_two_factor( int $user_id ): bool returns false when is_two_factor_plugin_active() is false, otherwise calls \Two_Factor_Core::is_user_using_two_factor( $user_id ) with // @phpstan-ignore class.notFound on the call line.
disable_two_factor_for_new_user( int $user_id ): void calls update_user_meta( $user_id, '_two_factor_enabled_providers', array() ) when is_two_factor_plugin_active() is true.
In the email-match branch of find_user(), return new WP_Error( self::ERROR_TWO_FACTOR_ENABLED ) ahead of the Hashed_User_ID::OPTION write when user_has_two_factor( $user->ID ) is true.
Update the find_user() docblock to @return WP_User|WP_Error|null and add a @since n.e.x.t note about the new WP_Error return when an email-matched user has two-factor enabled.
In create_user(), call disable_two_factor_for_new_user( $user_id ) between wp_insert_user() and wp_send_new_user_notifications().
In authenticate_user(), short-circuit immediately after find_user() with if ( is_wp_error( $user ) ) { return $this->get_error_redirect_url( $user->get_error_code() ); }.
In includes/Modules/Sign_In_With_Google.php
In handle_login_errors(), add case Authenticator::ERROR_TWO_FACTOR_ENABLED: $error->add( self::MODULE_SLUG, __( 'An existing account using two-factor authentication was detected with that email address. To connect an account using Sign in with Google, two-factor auth must be disabled for your user account.', 'google-site-kit' ) ); break;.
Test Coverage
In tests/phpunit/integration/Modules/Sign_In_With_Google/AuthenticatorTest.php, a test subclass overrides is_two_factor_plugin_active() and user_has_two_factor(). Five cases:
Plugin active, email-matched user with 2FA: authenticate_user() returns wp_login_url() with error=googlesitekit_auth_two_factor_enabled and Hashed_User_ID::OPTION is not written.
Plugin active, email-matched user without 2FA: Hashed_User_ID::OPTION is written and the user signs in.
Plugin inactive: the email-match branch runs even when the user already has _two_factor_enabled_providers meta set.
Plugin active, new user created: _two_factor_enabled_providers meta equals array() after authenticate_user() returns.
Plugin inactive, new user created: _two_factor_enabled_providers is not written.
In tests/phpunit/integration/Modules/Sign_In_With_GoogleTest.php:
$_GET['error'] = Authenticator::ERROR_TWO_FACTOR_ENABLED makes handle_login_errors() add a Sign_In_With_Google::MODULE_SLUG message containing "two-factor authentication".
An unrecognized $_GET['error'] value leaves the input WP_Error untouched.
No Storybook or VRT changes.
QA Brief
Set up Site Kit and connect the Sign in with Google module.
Sign out and click Sign in with Google with a Google Account that has no WordPress user.
Confirm it creates a new account and signs in.
Sign out and click Sign in with Google with the same account. Confirm it signs in again with no two-factor prompt.
Open that account under Users and confirm its Two-Factor Options stay off.
Two-factor stays on for a regular login
Turn on a Two-Factor Options provider for the new account.
Sign out and log in with its password. Confirm the two-factor challenge still shows.
Sign out and click Sign in with Google with the same account. Confirm it skips the challenge and signs in.
An existing account with two-factor enabled
Create a new WordPress user (one that has never signed in with Google) whose email matches a Google Account, then turn on a Two-Factor Options provider for it.
Sign out and click Sign in with Google with that account.
Confirm the login page shows the red error: An existing account using two-factor authentication was detected with that email address. To connect an account using Sign in with Google, two-factor auth must be disabled for your user account.
Confirm the user's Two-Factor Options stay on.
Turn off the user's Two-Factor Options, then click Sign in with Google with the same account. Confirm it links and signs in.
A new account with the Two-Factor plugin inactive
Deactivate the Two-Factor plugin.
Sign out and click Sign in with Google with a Google Account that has no WordPress user.
Bug Description
When Sign in with Google and the WordPress 2FA plugin are both enabled, creating an account works fine.
But signing in with that account, afterward, reportedly does not work.
This is likely because the 2FA flow fails.
In the case of users whose account uses SiwG, we should likely disable 2FA for that SiwG sign-in flow, relying on the Google Account to use 2FA—this is usually how social logins work 🤔
Steps to reproduce
Do not alter or remove anything below. The following sections will be managed by moderators only.
Acceptance criteria
Implementation Brief
includes/Modules/Sign_In_With_Google/Authenticator.phpconst ERROR_TWO_FACTOR_ENABLED = 'googlesitekit_auth_two_factor_enabled';with@since.@since):is_two_factor_plugin_active(): boolreturnsclass_exists( 'Two_Factor_Core' ).user_has_two_factor( int $user_id ): boolreturnsfalsewhenis_two_factor_plugin_active()isfalse, otherwise calls\Two_Factor_Core::is_user_using_two_factor( $user_id )with// @phpstan-ignore class.notFoundon the call line.disable_two_factor_for_new_user( int $user_id ): voidcallsupdate_user_meta( $user_id, '_two_factor_enabled_providers', array() )whenis_two_factor_plugin_active()istrue.find_user(), returnnew WP_Error( self::ERROR_TWO_FACTOR_ENABLED )ahead of theHashed_User_ID::OPTIONwrite whenuser_has_two_factor( $user->ID )istrue.find_user()docblock to@return WP_User|WP_Error|nulland add a@since n.e.x.tnote about the newWP_Errorreturn when an email-matched user has two-factor enabled.create_user(), calldisable_two_factor_for_new_user( $user_id )betweenwp_insert_user()andwp_send_new_user_notifications().authenticate_user(), short-circuit immediately afterfind_user()withif ( is_wp_error( $user ) ) { return $this->get_error_redirect_url( $user->get_error_code() ); }.includes/Modules/Sign_In_With_Google.phphandle_login_errors(), addcase Authenticator::ERROR_TWO_FACTOR_ENABLED: $error->add( self::MODULE_SLUG, __( 'An existing account using two-factor authentication was detected with that email address. To connect an account using Sign in with Google, two-factor auth must be disabled for your user account.', 'google-site-kit' ) ); break;.Test Coverage
tests/phpunit/integration/Modules/Sign_In_With_Google/AuthenticatorTest.php, a test subclass overridesis_two_factor_plugin_active()anduser_has_two_factor(). Five cases:authenticate_user()returnswp_login_url()witherror=googlesitekit_auth_two_factor_enabledandHashed_User_ID::OPTIONis not written.Hashed_User_ID::OPTIONis written and the user signs in._two_factor_enabled_providersmeta set._two_factor_enabled_providersmeta equalsarray()afterauthenticate_user()returns._two_factor_enabled_providersis not written.tests/phpunit/integration/Modules/Sign_In_With_GoogleTest.php:$_GET['error'] = Authenticator::ERROR_TWO_FACTOR_ENABLEDmakeshandle_login_errors()add aSign_In_With_Google::MODULE_SLUGmessage containing "two-factor authentication".$_GET['error']value leaves the inputWP_Erroruntouched.QA Brief
A new Sign in with Google account
Two-factor stays on for a regular login
An existing account with two-factor enabled
An existing account using two-factor authentication was detected with that email address. To connect an account using Sign in with Google, two-factor auth must be disabled for your user account.A new account with the Two-Factor plugin inactive
Changelog entry