Updating WordPress password without logging out

I recently created a plugin which among others forces the users to update their passwords during the setup phase.

After going live with the functionality, the client reported the users were confused as they could no longer access the website. I then realized that using wp_set_password() will update the password but also destroy the current user session forcing him to re-authenticate, which is good, but in my case the function was called after the initial headers were set so the user saw the loaded page but couldn’t use any of the features there.

The fix?

Use instead

$userdata = (array)wp_get_current_user();
$userdata['user_pass'] = $new_password;

This will update the password but also re-create the user session, as it shows at the end of the wp_update_user() function:

// Update the cookies if the password changed.
$current_user = wp_get_current_user();
if ( $current_user->ID == $ID ) {
   if ( isset($plaintext_pass) ) {
      // Here we calculate the expiration length of the current auth cookie and compare it to the default expiration.
      // If it's greater than this, then we know the user checked 'Remember Me' when they logged in.
      $logged_in_cookie    = wp_parse_auth_cookie( '', 'logged_in' );
      /** This filter is documented in wp-includes/pluggable.php */
      $default_cookie_life = apply_filters( 'auth_cookie_expiration', ( 2 * DAY_IN_SECONDS ), $ID, false );
      $remember            = ( ( $logged_in_cookie['expiration'] - time() ) > $default_cookie_life );
      wp_set_auth_cookie( $ID, $remember );

Note: this has to be called before the headers were sent as it will attempt to re-write them and you will get the “headers already sent” error. So I recommend running it in the wp action which runs exactly before anything is printed.