Make WordPress Core

Changeset 59633


Ignore:
Timestamp:
01/16/2025 03:33:31 PM (10 months ago)
Author:
johnbillion
Message:

Users: Retain the current session when a user changes their password.

Prior to this change a new session was unnecessarily created when a user changed their own password.

Existing authentication cookies for the user will still be invalidated regardless of whether they share the same session token because session cookie keys contain a substring of the password hash.

Props snicco, narenin, johnbillion

Fixes #61366

Location:
trunk
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/user.php

    r59595 r59633  
    27812781    if ( $current_user->ID === $user_id ) {
    27822782        if ( isset( $plaintext_pass ) ) {
    2783             wp_clear_auth_cookie();
    2784 
    27852783            /*
    27862784             * Here we calculate the expiration length of the current auth cookie and compare it to the default expiration.
     
    27912789            $default_cookie_life = apply_filters( 'auth_cookie_expiration', ( 2 * DAY_IN_SECONDS ), $user_id, false );
    27922790
     2791            wp_clear_auth_cookie();
     2792
    27932793            $remember = false;
     2794            $token    = '';
     2795
     2796            if ( false !== $logged_in_cookie ) {
     2797                $token = $logged_in_cookie['token'];
     2798            }
    27942799
    27952800            if ( false !== $logged_in_cookie && ( (int) $logged_in_cookie['expiration'] - time() ) > $default_cookie_life ) {
     
    27972802            }
    27982803
    2799             wp_set_auth_cookie( $user_id, $remember );
     2804            wp_set_auth_cookie( $user_id, $remember, '', $token );
    28002805        }
    28012806    }
  • trunk/tests/phpunit/tests/user.php

    r59232 r59633  
    6464        parent::set_up();
    6565
     66        add_action( 'set_auth_cookie', array( $this, 'action_set_auth_cookie' ), 10, 6 );
     67        add_action( 'set_logged_in_cookie', array( $this, 'action_set_logged_in_cookie' ), 10 );
     68        add_action( 'clear_auth_cookie', array( $this, 'action_clear_auth_cookie' ) );
     69
     70        $_COOKIE = array();
     71
    6672        $this->author = clone self::$_author;
     73    }
     74
     75    final public function action_set_auth_cookie(
     76        string $cookie,
     77        int $expire,
     78        int $expiration,
     79        int $user_id,
     80        string $scheme,
     81        string $token
     82    ): void {
     83        $_COOKIE[ SECURE_AUTH_COOKIE ] = $cookie;
     84        $_COOKIE[ AUTH_COOKIE ]        = $cookie;
     85    }
     86
     87    final public function action_set_logged_in_cookie( string $cookie ): void {
     88        $_COOKIE[ LOGGED_IN_COOKIE ] = $cookie;
     89    }
     90
     91    final public function action_clear_auth_cookie(): void {
     92        unset( $_COOKIE[ LOGGED_IN_COOKIE ] );
     93        unset( $_COOKIE[ SECURE_AUTH_COOKIE ] );
     94        unset( $_COOKIE[ AUTH_COOKIE ] );
    6795    }
    6896
     
    11231151    }
    11241152
     1153    /**
     1154     * @ticket 61366
     1155     * @dataProvider data_remember_user
     1156     */
     1157    public function test_changing_own_password_retains_current_session( bool $remember ) {
     1158        $user    = $this->author;
     1159        $manager = WP_Session_Tokens::get_instance( $user->ID );
     1160        $expiry  = $remember ? ( 2 * WEEK_IN_SECONDS ) : ( 2 * DAY_IN_SECONDS );
     1161        $token   = $manager->create( time() + $expiry );
     1162        $pass    = $user->user_pass;
     1163
     1164        wp_set_current_user( $user->ID );
     1165        wp_set_auth_cookie( $user->ID, $remember, '', $token );
     1166
     1167        $cookie   = $_COOKIE[ AUTH_COOKIE ];
     1168        $userdata = array(
     1169            'ID'        => $user->ID,
     1170            'user_pass' => 'my_new_password',
     1171        );
     1172        $updated  = wp_update_user( $userdata, $manager );
     1173        $parsed   = wp_parse_auth_cookie();
     1174
     1175        // Check the prerequisites:
     1176        $this->assertNotWPError( $updated );
     1177        $this->assertNotSame( $pass, get_userdata( $user->ID )->user_pass );
     1178
     1179        // Check the session token:
     1180        $this->assertSame( $token, $parsed['token'] );
     1181        $this->assertCount( 1, $manager->get_all() );
     1182
     1183        // Check that the newly set auth cookie is valid:
     1184        $this->assertSame( $user->ID, wp_validate_auth_cookie() );
     1185
     1186        // Check that, despite the session token reuse, the old auth cookie should now be invalid because the password changed:
     1187        $this->assertFalse( wp_validate_auth_cookie( $cookie ) );
     1188    }
     1189
     1190    public function data_remember_user() {
     1191        return array(
     1192            array( true ),
     1193            array( false ),
     1194        );
     1195    }
     1196
    11251197    public function test_search_users_login() {
    11261198        $users = get_users(
Note: See TracChangeset for help on using the changeset viewer.