Filter Hook since 2.8.0
authenticate
The core WordPress login/authentication filter
Description
authenticate is the chain that decides whether login credentials are valid — every auth method, from core's own password check to SSO plugins, hooks into this same filter.
When it runs
Called from wp_authenticate() (used by wp-login.php and wp_signon()) — runs through a priority chain of default core checks (username/password, cookie, application passwords).
Signature
apply_filters( 'authenticate', WP_User|WP_Error|null $user, string $username, string $password );Parameters
$userWP_User|WP_Error|null — Current authentication result so far.$usernamestring — Submitted username.$passwordstring — Submitted password.
Examples
Basic
add_filter( 'authenticate', function( $user, $username ) {
if ( 'blocked_user' === $username ) {
return new WP_Error( 'blocked', 'This account is disabled.' );
}
return $user;
}, 30, 3 );Block a specific username from logging in regardless of password.
Real case
add_filter( 'authenticate', function( $user ) {
if ( $user instanceof WP_User && ! get_user_meta( $user->ID, '2fa_verified', true ) ) {
return new WP_Error( '2fa_required', 'Two-factor verification required.' );
}
return $user;
}, 40, 1 );Add an extra gate after core's own check already resolved a valid WP_User, before login completes.
Common Use Cases
- Add a second authentication factor before allowing login
- Block specific usernames or patterns
- Integrate an SSO/external identity provider
- Log failed or suspicious login attempts
Common mistakes
- Returning null instead of a WP_Error to reject login — WordPress then falls through to the next registered check instead of actually blocking it
Related hooks
FAQ
How do I reject a login attempt from this filter?
Return a WP_Error object. Returning null lets WordPress continue checking other registered authenticate callbacks instead of stopping the login outright.
Source: wp-includes/user.php