Force Strong Passwords for New and Updated Accounts
Requires new and updated user passwords to meet a minimum length and character-variety rule, instead of relying on users to notice WordPress's visual strength meter.
- Difficulty
- Intermediate
- Reading time
- ~1 min
- Where to add it
- A small custom plugin
- Last updated
The Problem
WordPress shows a password strength meter on the registration and profile-update screens, but it's purely a visual suggestion — a user can ignore a "Very Weak" warning entirely and save a short, simple password with no error stopping them. On a site with multiple authors, contributors, or customer accounts, that means your actual account security depends entirely on every individual user making a good judgment call that nothing on the server side actually enforces. The `user_profile_update_errors` and `registration_errors` hooks both accept a `WP_Error` object by reference, which is exactly what's needed to turn that visual-only suggestion into a rule WordPress will genuinely refuse to save a password against.
The Code
add_action( 'user_profile_update_errors', 'devmubs_enforce_strong_password', 10, 1 );
add_filter( 'registration_errors', 'devmubs_enforce_strong_password_registration', 10, 1 );
function devmubs_enforce_strong_password( $errors ) {
if ( empty( $_POST['pass1'] ) ) {
return;
}
devmubs_validate_password_strength( wp_unslash( $_POST['pass1'] ), $errors );
}
function devmubs_enforce_strong_password_registration( $errors ) {
if ( empty( $_POST['user_pass'] ) ) {
return $errors;
}
devmubs_validate_password_strength( wp_unslash( $_POST['user_pass'] ), $errors );
return $errors;
}
function devmubs_validate_password_strength( $password, $errors ) {
if ( strlen( $password ) < 10 ) {
$errors->add( 'password_too_short', __( 'Error: Password must be at least 10 characters long.' ) );
return;
}
if ( ! preg_match( '/[A-Za-z]/', $password ) || ! preg_match( '/[0-9]/', $password ) ) {
$errors->add( 'password_too_weak', __( 'Error: Password must contain both letters and numbers.' ) );
}
}How It Works
`user_profile_update_errors` fires on the admin profile-edit screen (used both when a user edits their own profile and when an admin edits someone else's), while `registration_errors` fires on the front-end registration form — they're separate code paths for separate screens, which is why both are hooked, sharing one validation function so the length and character rules stay identical between them. Each hook passes a `WP_Error` object; calling `$errors->add()` on it adds a message without needing to return anything special, since WordPress checks after the hook runs whether that object has accumulated any errors and blocks the save entirely if it has — the user sees your message and the password is never written to the database. `wp_unslash()` removes the extra backslashes WordPress adds to `$_POST` data by default, so the length and character checks run against the password's actual literal value rather than an escaped version of it.
Where To Add This
A small custom plugin. This is application logic with no relationship to how the site looks, so it belongs in a small plugin — that way the rule keeps applying even if the site's theme changes later.
Warnings & Caveats
- This validates the registration form and the profile-edit screen, but not the "Lost your password" reset-by-email flow — that uses a separate `validate_password_reset` hook if you want the same rule enforced there too.
- This doesn't retroactively check existing passwords — it only applies the next time a password is created or changed.
- Always back up your site before adding custom code.