I've been using wp_signon for a long time in a project:

//Do the actual login for WP User
$creds = array();
$creds['user_login'] = $skuser_name;
$creds['user_password'] = $skuser_pass;
$creds['remember'] = true;
$user = wp_signon( $creds, false ); 

This have been working for a long time. I recently added plugin Wordfence which included recaptcha (invislbe) for login and registration forms and those obviously do work.

After installation of that plugin my custom loginforms with code above did not work. After some research I figured out that it was the recaptcha in combination with my custom loginform that uses wp_signon that was the issue.

I get the error (when using correct username and password):

//VERIFICATION REQUIRED: Additional verification is required for login. Please check the email address associated with the account for a verification link.

When I deactive recaptcha which is included in WordFence - plugin -> my custom loginform does work.

I have keys that are needed for the actual recaptcha but I can't figure what I have to do to integrate this with wp_signon!? Is it possible to integrate recaptcha with wp_signon or do I have to create a custom wp_signon function?

Please point me in right direction! Thank you!

  • Wordfence has a filter named wordfence_ls_require_captcha. Have you tried that?
    – Sally CJ
    Mar 29, 2020 at 13:56
  • I mean, you can use that filter if you just want to bypass the captcha while doing the wp_signon(). But if you actually want to add the captcha to your custom form, then you can ignore that filter.
    – Sally CJ
    Mar 29, 2020 at 14:57
  • @SallyCJ - thanks for telliing me about this. I did not know about this filter. This seems like a lazy mens way though. I really would want the recaptcha to work (integrated), not disabled - on my custom login forms. Mar 29, 2020 at 20:09
  • Alright then. And I've posted an answer. Let me know how it goes.
    – Sally CJ
    Mar 30, 2020 at 4:19
  • 1
    @SallyCJ - wow thanks a LOT! Mar 30, 2020 at 14:54

1 Answer 1


So Wordfence uses JavaScript to add the CAPTCHA fields to the login/registration form, but by default only on https://example.com/wp-login.php.

And if you want to add the fields to your form, or integrate the CAPTCHA security with your custom login form, the steps are:

  1. Enqueue the (re)CAPTCHA scripts, preferably only on the page having the custom form:

    add_action( 'wp_enqueue_scripts', function () {
        if ( is_page( 'my-page' ) &&
            class_exists( '\WordfenceLS\Controller_WordfenceLS' )
        ) {
    } );

    The above would load the scripts only on the my-page Page, so you should change the slug or use another conditional tag like is_single().

  2. Your custom form has to meet these conditions:

    1. The username field must be named log (e.g. <input name="log" />).

    2. The password field must be named pwd (e.g. <input name="pwd" />).

    3. The submit button's id must be wp-submit (e.g. <input id="wp-submit" type="submit" />).

    4. There must be no other forms having those fields, i.e. there must be no other form fields having the same name or id.

    5. Wordfence will run an AJAX request to check the credentials and when there's an error like wrong password, Wordfence will add the error message after a h1 (heading level 1) inside the element with the id of login.

      So you need to make sure those two elements (#login and #login > h1) both exist — see the sample form code below.

    And those are, unfortunately, limitations in the Wordfence's custom login script, which you can find it in wp-content/plugins/wordfence/modules/login-security/js and the file name looks like login.1581523568.js (i.e. login.<numbers>.js). You may copy and modify the script (i.e. remove those 5 limitations), then enqueue it instead of the default, but you'll need to try doing so on your own.

    Also, if you use wp_login_form() (with a custom action value), you would only need to add the elements mentioned in #5 above.

Code I used for testing:

The form, shown on https://example.com/my-page/:

<div id="login">

    <!-- Wordfence places AJAX error here -->

    <form method="post" action="">
        <input name="log" type="text" placeholder="Username" />
        <input name="pwd" type="password" placeholder="Password" />

        <input type="hidden" name="action" value="my_login" />
        <?php wp_nonce_field( 'my-login' ); ?>

        <input type="submit" id="wp-submit" />

And the PHP, which calls wp_signon():

add_action( 'init', function () {
    if (
        wp_doing_ajax() || empty( $_POST['_wpnonce'] ) ||
        ( ! ( isset( $_POST['log'], $_POST['pwd'] ) ) ) ||
        ! wp_verify_nonce( $_POST['_wpnonce'], 'my-login' )
    ) {

    $creds = array();

    $creds['user_login']    = $_POST['log'];
    $creds['user_password'] = $_POST['pwd'];
    $creds['remember']      = true;

    $user = wp_signon( $creds, false );
    if ( is_wp_error( $user ) ) {
        wp_die( $user );
    } else {
        wp_redirect( home_url( wp_get_referer() ) );
} );

Additional Notes

As I mentioned in the comment, if you just want to bypass the CAPTCHA validation while doing wp_signon(), you can use the wordfence_ls_require_captcha filter:

add_filter( 'wordfence_ls_require_captcha', '__return_false' );
// call wp_signon() here
remove_filter( 'wordfence_ls_require_captcha', '__return_false' );
  • 1
    Thanks a lot! It would be foolish NOT to accept this answer. I don't think it could be any clearer than this. Mar 30, 2020 at 14:55
  • So would you mind marking the answer as correct, unless you intend to write your own answer? :)
    – Sally CJ
    Mar 30, 2020 at 22:39
  • ofc! I thought it was marked as accepted when I gave away my 200 points (Why else would I do that (asking SO here)). I apolgoize and thanks one again! Mar 31, 2020 at 20:05
  • 1
    Nope, awarding a bounty does not automatically accept the answer (or mark it as correct), just as accepting an answer doesn't automatically upvote the answer.. eheh. :) Anyway, +1 for the question! ;)
    – Sally CJ
    Mar 31, 2020 at 22:33
  • Extremely helpful, @sally-cj Thank you! I just wanted to add that after implementing this, I couldn't access the WP admin area, I'd get sent to the standard login page with ?reauth=1. This post gave me the solution, which was to call wp_set_auth_cookie($user->ID); after wp_signon. Doesn't seem like it should be necessary, but it solved my problem. May 23 at 19:19

Your Answer

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

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