I ate up a bit of time tracking all the pieces down, but in the end it’s pretty simple to build a custom login form which is compatible with the new Wordfence 2FA, though I only tested recaptcha, not the otp app yet.
For a demo, I made a /login/ page to display the custom login form. In functions.php add:
add_filter( 'login_url', function( $login_url, $redirect, $force_reauth ) {
$login_page = home_url( '/login/' );
$login_url = add_query_arg( 'redirect_to', $redirect, $login_page );
return $login_url;
}, 10, 3 );
add_filter( 'logout_url', function( $logout_url, $redirect ) {
$login_page = home_url( '/login/' );
$logout_url = add_query_arg( 'redirect_to', $login_page, $logout_url );
return $logout_url;
}, 10, 2 );
The login_url filter is needed to make the link in the verification url’s point to the /login/ page.
In the template displaying the custom login page you need to mimic a little behavior from wp-login.php. I found 4 things were needed: to enqueue login scripts, do the login_init action (which calls wordfence::loginInitAction), do the login_form action in the middle of the login form (which calls wordfence::showTwoFactorField) by tying it to the login_form_middle action, and include appropriate markup so the ‘#login > h1’ selector has a match to place error messages.
if ( is_user_logged_in() ) {
?> <p>You are already logged in. <a href="/wp-login.php?action=logout&redirect=/login">Log out</a>.</p> <?php
} else {
add_action( 'login_form_middle', function() { do_action( 'login_form' ); } );
do_action( 'login_enqueue_scripts' );
do_action( 'login_init' );
?> <div id="login"><h1 style="display: none;"></h1></div> <?php
wp_login_form( array('redirect' => home_url()) );
}
And don’t forget to style ‘.login_error’ to call attention to the ‘VERIFICATION REQUIRED …’ error.
There are a few things missing that the full wp-login.php would include (eg. wordfence::wfLogHumanHeader and wordfence::addSyncAttackDataAjax which are normally called by login_head action), so there is room for improvement if Wordfence were to officially support custom login pages. Of note, I managed to lock myself out during testing, and Wordfence’s ‘You are temporarily locked out’ block was preceded by ‘ Cannot modify header information – headers already sent’ warnings. But this is much better than having those login forms completely unprotected.
@wfdave: is there an official feature request open for supporting custom login pages? If not, please consider this a request to create one. On sites which use them (and ours uses it exclusively), there’s really a need to have a good login security solution. Thanks!