I'm building a custom login page for clients and wish to keep the wp-login page for site administrators.

For checking for empty fields I'm using the code:

function verify_user_pass($user, $username, $password) {
    $login_page  = home_url('/login/');
    if($username == "" || $password == "") {
        wp_redirect($login_page . "?login=empty");
add_filter('authenticate', 'verify_user_pass', 1, 3);

But this is interfering with the wp-login, as it checks to early and redirects to the "client login page" right after landing on the wp-login page.

Is there any other approach for checking empty fields that doesn't interfere with the wp-login?

Thank you!

  • This filter does not return, filters always return. This is the same as adding return null; to the end of the function
    – Tom J Nowell
    Jul 29, 2021 at 14:50

1 Answer 1


Part of the problem is you've set the priority of your filter to "1" which means it will run first. Since authenticate is going to run on any login (wp-login.php or your front-end login page), you probably need to start with setting it to the default (10). Otherwise, it's just going to hijack your wp-login.php.

Since you don't need to do this on wp-login.php, you could also check to make sure that's not the current page when you run your custom validation. I did that in your function by checking the global 'pagenow' is not 'wp-login.php'.

function verify_user_pass( $user, $username, $password ) {
    if ( $GLOBALS['pagenow'] != 'wp-login.php' ) {
        $login_page  = home_url( 'login/' );
        if ( "" == $username || "" == $password ) {
            wp_redirect( add_query_arg( 'login', 'empty', $login_page ) );

    return $user;
add_filter( 'authenticate', 'verify_user_pass', 10, 3 );

Some other things I changed:

  • home_url() does not need a leading slash for slugs - it will put that in automatically.
  • changed your comparisons to "yoda conditions" ("" == $username) - it's a good habit to get into because it catches type/syntax errors (like if you mistype "=" instead of "==").
  • use add_query_arg() to add your query argument to the URL. That way it will be added properly, even if there are other query arguments in the URL.
  • Note that this is a filter, not an action. Therefore, you need to make sure you return what the filter hook is filtering. In the case of authenticate that's the $user object (which may also contain a WP_Error object). If you don't return this at the end, you'll break anything outside your custom process that also runs this filter (i.e. the main wp-login.php).
  • The conditional check for current page is making the function not work correctly. When at the custom login page, any empty field will make the page redirect to the wp-login page. Dec 20, 2018 at 11:17
  • My original answer was to change the priority, but as I continued writing it I added the conditional check. With the conditional check in place, you may actually be successful setting the priority back to 1. However, since we're only looking at one piece of a full process that is kind of out of context, that's hard to say for certain. You're not actually using authenticate as a filter, but as an action. So you may actually be better off checking for empty fields prior to starting WP's login process (assuming you're firing wp_signon() hooked to init or something similar).
    – butlerblog
    Dec 20, 2018 at 13:21
  • It doesn't help setting the priority back to 1. All I'm doing is basically what's described in this article (link), without the redirection from the wp-login.php page to the new custom login page. Dec 20, 2018 at 14:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.