Force user to change their password on the frontend at the first login and password policy

This is a multi-faceted issue that probably seems (well, to me at least) easy at first. Not sure if the code works, however, it’s close to working but most importantly, showcases the flow of how things need to happen:

/**
 * First of all, hook up to the login process.
 */
add_action( 'wp_login', function( $user_login, $user ) {
    //Let's see if the user that just logged in has a proper password, meaning, he reset his default one to a custom one.
    $has_proper_password = get_user_meta( $user->ID, 'has_proper_password', True );

    //If he doesn't
    if( $has_proper_password === '0' ) {
        //Always redirect him to that password panel.
        wp_safe_redirect( wp_login_url( '?action=lostpassword' ) );
    }
});

So, before anything, you’re hooking to the login process. I assume you’re generating a default password to a user and mailing it to them and the reason for you wanting to change that is so that the plain-text is never valid if an attacker gets access to the medium it was sent to. Back to topic, the core of this sub-system will be an user_meta with the flag has_proper_password, this is where you’ll store a flag that tells us if a given user has had his default password reset. Whenever they login, if they hadn’t changed their default password, they’ll just be redirected to that screen of yours. Moving on.

You’ll then want to grab the user’s current hashed password when he’s attempting a reset. The hook password_reset fires right before that happens:

//Let's store the old password, before the reset happened.
$old_password_hash="";

//We'll grab it from the 'password_reset' hook which fires right before the password is updated.
add_action( 'password_reset', function( $user, $new_pass ) {
    $old_password_hash = $user->user_pass;
});

Great, now we have the user’s hash. Let’s assume that a successful change of passwords happened. To sum it all up, you want to go back to that user_meta and if the user hasn’t had his default password changed, follow the logic of:

  1. Is the new password the same as the old one? If yes, redirect back to that change password screen with a new message or something of the sorts. If not, proceed.
  2. So, the new password is a completely new one — valid too, great, **all we’ll do now is update that user_meta to tell the system that, when the user logs in once again, it shouldn’t stop him and ask for a valid password since it’s already there.
  3. Redirect either to login or if you wanna get fancy, pass the session through code so the user doesn’t have to login once again.

All of this, in code:

//Second of all, hook up to the change password process.
add_action( 'after_password_reset', function( $user, $new_pass ) {
    $has_proper_password = get_user_meta( $user->ID, 'has_proper_password', True );

    /**
     * If, before this reset happened, the user still didn't have a proper password and now
     * he supposedly does
     */
    if( $has_proper_password === '0' ) {

        //First of all, is the password that was just updated the same as the one that we gave to them?
        if( wp_check_password( $new_pass, $old_password_hash ) === False ) {
            //Redirect back to that reset page? I don't know.
        }

        //But if it isn't and therefore the newly picked password is a different one, let the system know by attaching some data to the user.
        $update = add_user_meta(
            $user->ID,
            'has_proper_password',
            '1'
        );

        //If the update failed, no worries, next time the user will just be prompted to reset again, however, this is an issue you'll have to solve.
        if( $update === False ) {
            return;
        }
    }
});