Commit 25d4b38b994 for woocommerce
commit 25d4b38b994f44fc19fa64fa7d2c9d8b018d402e
Author: Lucio Giannotta <lucio.giannotta@a8c.com>
Date: Mon Sep 7 19:20:50 2026 +0200
Preserve login only for the current user after password reset (#68387)
When a user resets their password, we currently automatically log them in with that account, even if the browser was already logged in as somebody else.
This is not an intentional design decision: it came from #51227 and the delayed account creation flow. In that flow, the customer creates an account from the order confirmation page and is already logged in, which makes sense, but was added unconditionally.
Here we fix that, which also fixes a bunch of other problems connected to it.
diff --git a/plugins/woocommerce/changelog/fix-password-reset-preserve-login b/plugins/woocommerce/changelog/fix-password-reset-preserve-login
new file mode 100644
index 00000000000..654263534a0
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-password-reset-preserve-login
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Preserve the current customer's login after a password reset without logging in a different customer.
diff --git a/plugins/woocommerce/includes/shortcodes/class-wc-shortcode-my-account.php b/plugins/woocommerce/includes/shortcodes/class-wc-shortcode-my-account.php
index 0b5fe9198eb..5e3c7d2d781 100644
--- a/plugins/woocommerce/includes/shortcodes/class-wc-shortcode-my-account.php
+++ b/plugins/woocommerce/includes/shortcodes/class-wc-shortcode-my-account.php
@@ -421,7 +421,9 @@ class WC_Shortcode_My_Account {
}
self::set_reset_password_cookie();
- wc_set_customer_auth_cookie( $user->ID );
+ if ( get_current_user_id() === $user->ID ) {
+ wc_set_customer_auth_cookie( $user->ID );
+ }
// phpcs:ignore WooCommerce.Commenting.CommentHooks.MissingHookComment
if ( ! apply_filters( 'woocommerce_disable_password_change_notification', false ) ) {
diff --git a/plugins/woocommerce/tests/php/includes/shortcodes/class-wc-shortcode-my-account-test.php b/plugins/woocommerce/tests/php/includes/shortcodes/class-wc-shortcode-my-account-test.php
new file mode 100644
index 00000000000..734ab3f1501
--- /dev/null
+++ b/plugins/woocommerce/tests/php/includes/shortcodes/class-wc-shortcode-my-account-test.php
@@ -0,0 +1,88 @@
+<?php
+declare( strict_types = 1 );
+
+/**
+ * Tests for WC_Shortcode_My_Account.
+ */
+class WC_Shortcode_My_Account_Test extends WC_Unit_Test_Case {
+
+ /**
+ * User IDs for which an authentication cookie was generated.
+ *
+ * @var int[]
+ */
+ private $auth_cookie_user_ids = array();
+
+ /**
+ * Set up test fixtures.
+ */
+ public function setUp(): void {
+ parent::setUp();
+
+ add_action( 'set_auth_cookie', array( $this, 'record_auth_cookie_user_id' ), 10, 4 );
+ add_filter( 'send_auth_cookies', '__return_false' );
+ add_filter( 'woocommerce_disable_password_change_notification', '__return_true' );
+ }
+
+ /**
+ * Record the user ID when WordPress generates an authentication cookie.
+ *
+ * @param string $auth_cookie Authentication cookie value.
+ * @param int $expire Login grace period expiration.
+ * @param int $expiration Authentication cookie expiration.
+ * @param int $user_id User ID.
+ */
+ public function record_auth_cookie_user_id( $auth_cookie, $expire, $expiration, $user_id ): void {
+ $this->auth_cookie_user_ids[] = $user_id;
+ }
+
+ /**
+ * Reset a password without emitting a cookie header from the CLI test runner.
+ *
+ * @param WP_User $user User whose password is being reset.
+ * @param string $new_pass New password.
+ */
+ private function reset_password( $user, $new_pass ): void {
+ // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged -- setcookie() cannot be mocked and the test bootstrap has already sent output.
+ @WC_Shortcode_My_Account::reset_password( $user, $new_pass );
+ }
+
+ /**
+ * @testdox Password reset preserves the current user's login.
+ */
+ public function test_reset_password_preserves_current_user_login(): void {
+ $user = self::factory()->user->create_and_get();
+ wp_set_current_user( $user->ID );
+
+ $this->reset_password( $user, 'new-password' );
+
+ $this->assertSame( array( $user->ID ), $this->auth_cookie_user_ids );
+ }
+
+ /**
+ * @testdox Password reset does not log in a logged-out user.
+ */
+ public function test_reset_password_does_not_log_in_logged_out_user(): void {
+ $user = self::factory()->user->create_and_get();
+ wp_set_current_user( 0 );
+
+ $this->reset_password( $user, 'new-password' );
+
+ $this->assertEmpty( $this->auth_cookie_user_ids );
+ $this->assertSame( 0, get_current_user_id() );
+ }
+
+ /**
+ * @testdox Password reset does not replace a different user's login.
+ */
+ public function test_reset_password_does_not_replace_different_user_login(): void {
+ $current_user = self::factory()->user->create_and_get();
+ $reset_user = self::factory()->user->create_and_get();
+ wp_set_current_user( $current_user->ID );
+
+ $this->reset_password( $reset_user, 'new-password' );
+
+ $this->assertEmpty( $this->auth_cookie_user_ids );
+ $this->assertSame( $current_user->ID, get_current_user_id() );
+ }
+}