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!
1 Answer
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:
-
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' ) ) { \WordfenceLS\Controller_WordfenceLS::shared()->_login_enqueue_scripts(); } } );
The above would load the scripts only on the
my-page
Page, so you should change the slug or use another conditional tag likeis_single()
. -
Your custom form has to meet these conditions:
-
The username field must be named
log
(e.g.<input name="log" />
). -
The password field must be named
pwd
(e.g.<input name="pwd" />
). -
The submit button’s
id
must bewp-submit
(e.g.<input id="wp-submit" type="submit" />
). -
There must be no other forms having those fields, i.e. there must be no other form fields having the same
name
orid
. -
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 theid
oflogin
.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 likelogin.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 customaction
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">
<h1>Login</h1>
<!-- 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" />
</form>
</div>
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' )
) {
return;
}
$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() ) );
exit;
}
} );
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' );