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.

Leave a 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.
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.