Disable password reset in WordPress

WordPress password reset feature has been exploited by hackers in the past, therefore disabling it is a considerable security feature. In most cases WordPress websites will only have a limited number of users who need to access the admin interface – e.g. admins themselves, shop managers or content editors, therefore in this scenario, it is more than healthy to entrust the password management to the main administrator of the site or at a minimum – to add some limitations for this feature.

Disable WordPress password reset for all users

To do this, you can either create a php file which must be placed in “wp-content/mu-plugins” folder (technically a “must use” plugin) and add the following code to it, or you can just append the code to your WordPress theme functions file.

/*Prevents users from resetting their password via the WordPress Login forms*/
/*Note the priority of this filter - it is specifically set to 30, so it can override other of its declarations in the code*/
add_filter( 'allow_password_reset', '__return_false', 30, 1 );

/*Disables direct access to password reset forms present in WordPress Login interface*/
add_action( "login_init", function() {
    if (isset( $_GET['action'] )){
        if ( in_array( $_GET['action'], array('lostpassword', 'retrievepassword') ) ) {
            wp_redirect( wp_login_url(), 301 );
            exit;
        }
    }
});

/*Removes the "Lost your password" text from login screen*/
add_filter( 'lost_password_html_link',  '__return_false' );

The comments I’ve left in the code are self-explanatory. These three customizations:

  • denies the password reset feature for all users
  • redirects users away from the default password reset forms (if they try to access them)
  • removes a “Lost Password” link from the WordPress admin login screen

Disable the password reset only for specific users

Sometimes it is necessary to leave the password reset feature enabled for a specific set of users. You can adjust the previous code snippet by modifying the “allow_password_reset” filter to something like this:

add_filter( 'allow_password_reset', 'dwp_deny_pwd_reset_for_staff', 99, 2 );

function dwp_deny_pwd_reset_for_staff($allow, $user_id) {
        if(!empty($user_id)) {
            $user_meta = get_userdata($user_id);
            if(!empty($user_meta)) {
                $user_roles = $user_meta->roles;
                 if(!in_array('customer', $user_roles) && !in_array('subscriber', $user_roles)) {
                    return false;
                 }
            }
        }
        return $allow;
}

This will leave the password reset feature enabled for subscribers and WooCommerce customers while disabling it for other user roles.

WP-Members and allow_password_reset filter compatibility issues

WP-Members Membership plugin for WordPress by Chad Butler is a quite popular choice for membership management and custom registration forms, but despite its popularity, in its last version (3.4.9.1) it has a bug which conflicts with other password reset limitations.

This lies in the usage of allow_password_reset – a filter integrated in WordPress which allows to declare specific conditions when a password reset for WordPress users should be allowed or not. When a custom override for this filter has been declared in other plugins or the site theme, WP-Members either:

  • enforces its own customizations and basically allows to request a password reset for each and every user;
  • crashes the site with throwing a PHP Fatal error when a larger priority number for the other allow_password_reset override is being used

There’s however a simple workaround which fixes the mentioned conflict. For this to work, you need to add this code snippet in your WordPress theme functions file or place / append it to a must-use plugin:

add_filter('wpmem_pwdreset_args', 'dwp_fix_pwd_reset_restrictions_wp_members', 10, 1);
function dwp_fix_pwd_reset_restrictions_wp_members($args) {
    if(!empty($args['user'])) {
        $user_id = strpos($args['user'], '@') !== false ? email_exists($args['user']) : username_exists($args['user']);
        if(!empty($user_id)) {
            $should_allow_reset_password = apply_filters( 'allow_password_reset', true, $user_id);
            $args['user'] = !empty($should_allow_reset_password)? $args['user'] : '';
        }
    }
    return $args;
}

What this does – it catches an e-mail address or username that was entered in the password reset form and checks it against the site database – if it is a valid user, it then checks if a password reset feature for this user is enabled by applying the “allow_password_reset” filter to the user ID. If the password reset is not available for the particular user, it will artificially trigger an error about the e-mail/username not being found in the system.

1 Comment on Disable password reset in WordPress
About the author
I'm a full-stack WordPress developer with a 10+ years of solid experience in the core web development languages, development processes / techniques, web security, Linux server management and with pretty good understanding about proper semantics, UX/UI, technical SEO, good design and basic knowledge of company leadership. On top of that - a distant 5+ years experience as a computer and electronics repair technician which often enables me to understand also how the things work at the hardware level.

One thought on “Disable password reset in WordPress

  1. Hi Edgars,
    just to say thank for putting this together.
    I’ve been searching for something simple to tackle this problem without using yet another plugin.
    This works perfectly and is what I was after.

    Many thanks
    Mike.

Your feedback matters!…
I hope you found this article helpful. Feel free to add some comments - your feedback is very important to me, as it drives my motivation and helps me to improve the content.