You can add a low priority authenticate hook that runs after all the other hooks and rejects authentication for a specific user ID:
function wpse_384212_ban_user_id( $user, $username, $password ) {
// At this point $user is either a WP_User object if they've successfully logged in,
// or null or a WP_Error if they haven't. We want to reject users by ID.
if ( $user instanceof WP_User ) {
// This is a successfully authenticated user. Check their ID.
$banned_user_ids = array( 3, 6, 10 ); // could also store these in a site option
if ( in_array( $user->ID, $banned_user_ids ) ) {
return new WP_Error( 'user_banned', 'You are banned' );
}
}
// Else return the user or error from previous authentication filters
return $user;
}
add_filter( 'authenticate', 'wpse_384212_ban_user_id', 999, 3 );
This rejects users who have otherwise logged in successfully. If you wanted to reject them whether they managed to log in or not, you'll need to look up the user to fetch their ID for the extra check:
function wpse_384212_ban_user_id( $user, $username, $password ) {
// At this point $user is either a WP_User object if they've successfully logged in,
// or null or a WP_Error if they haven't. We want to reject users by ID.
$banned_user_ids = array( 3, 6, 10 ); // could also store these in a site option
if ( $user instanceof WP_User ) {
// This is a successfully authenticated user. Check their ID.
if ( in_array( $user->ID, $banned_user_ids ) ) {
return new WP_Error( 'user_banned', 'You are banned' );
}
} elseif ($username) {
// Unsuccessful login but we have a username.
// Look up the user by username or email to see if they are a banned user
$login_user = get_user_by( 'login', $username );
if ( ! $login_user && is_email( $username ) ) {
$login_user = get_user_by( 'email', $username );
}
if ( $login_user instanceof WP_User ) {
// This was a failed login for a valid user. Check the user's ID
if ( in_array( $login_user->ID, $banned_user_ids ) ) {
return new WP_Error( 'user_banned', 'You are banned' );
}
}
}
// Else return the user or error from previous authentication filters
return $user;
}
add_filter( 'authenticate', 'wpse_384212_ban_user_id', 999, 3 );
If this is a multisite then these would need to go in a mu-plugin.