1

I have 3 users roles on my platform with no access to the WordPress backoffice "external_user1" , "external_user2", "external_user3".

I need to force every user with one of this roles to change his password at the first login. by the way i use the WordPress login form.

So if the user enter the correct ID and password he is redirected to : wp-login.php?action=lostpassword for reset the password. as you can see on the picture below : enter image description here

At this time, he enters again the ID and a reset mail is send to the user.

When the user click to the mail link he is redirected to reset page. and when he tries to change the password i need him to type on the keyboard the old one. after that he can access.

And the last one is about password policy : 8 characters with at last 1 uppercase 1 lowercase 1 Number 1 special character

Thanks.

1
  • What have you tried so far?
    – Himad
    Commented May 27, 2020 at 10:25

2 Answers 2

2

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;
        }
    }
});
5
  • Couldn't have said it better myself!
    – Mort 1305
    Commented May 31, 2020 at 1:42
  • Sorry for my late answer (i was sick). I tried your code but it doesn't work.
    – Samuel
    Commented Jun 8, 2020 at 20:35
  • @sampaii It's the first paragraph "this code is juat close to what works". I don't know you, maybe you have a bad situation and just trying to make a buck on the side, but if you didn't understand what my answer is, well, this is a developer's Q&A site, I assume you understand basics of WordPress and then you're a programmer yourself. Having looked back now, I think this question is more so a "plugin recommendatation". Commented Jun 9, 2020 at 21:17
  • I tried the code in my functions.php and got the error below after login: There has been a critical error on this website.
    – user229486
    Commented Jan 27, 2023 at 15:22
  • Which code, Daniel’s? Can you look at your server error log to get more details what went wrong? Or the site should have emailed you the error too
    – Rup
    Commented Jan 27, 2023 at 21:05
-2

There are a number of useful plugins that do just this. They even have extra features you didn't mention like two-factor authentication.

Some of these are free. Or at least have free trials or free plans.

1
  • Thanks but my objectif is to force the change of the password at the first login in frontend. the plugins you list doesn't offer that kind of feature.
    – Samuel
    Commented Jun 8, 2020 at 20:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.