I’ve build quite a few custom login-forms in WordPress. There are, as always, a lot of ways to realize that, but nearly all the clients I worked with, had similar requirements: On the one hand they wanted to preserve the usual WordPress login-form to let administrators, editors and authors sign in into wp-admin. On the other hand they wanted another usergroup to sign in into their site via a fully customized WordPress login-screen, to download protected documents or whatever.
Customized WordPress login-form
Generally the problem is solved fairly easy, using the WordPress-API. You can print out a standard login-form by using wp_login_form wherever in your theme you want it. There is even a way to specify the page, the user should be redirected to after a successful login. Here an example, redirecting you to the home page:
<?php wp_login_form( array( 'redirect' => get_bloginfo('url'), 'form_id' => 'sign-in', 'label_log_in' => __( 'Sign in' ), ) ); ?>
If you need to adjust the HTML-output, you can build your own sign in form markup by saving a file named searchform.php in your theme folder. Than you are just a few stylesheet-rules away from your customized form, with working login.
Handling login-fails
The problems begin when you fail to login, because writing in a wrong username and/or password doesn’t redirect you to your customized form, it redirects you to the wp-admin site. Since the signing-in user is not supposed to login to wp-admin, this redirect doesn’t make any sense. But again we find a straight forward solution in the WordPress-API. Add these lines to your functions.php:
function custom_login_failed( $username ) { $referrer = $_SERVER['HTTP_REFERER']; if ( !empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin') ) { // redirect to your login page, you might want to add a parameter login_failed // to show an error message or something like that wp_redirect( ... ); exit; } } add_action( 'wp_login_failed', 'custom_login_failed' );
You might think that’s all, but not so fast …
Handling empty logins
There is yet another way to get redirected to the wp-admin login form, and that is when you just don’t enter anything. Submit the form with an empty username and password field and you are on wp-admin again. That is because the wp_authenticate function, which handles redirection ignores empty_username and empty_password as error codes and that is why our wp_login_failed action never fires. The solution is to change these error codes, if the user logs in from another site than wp-admin or wp-login.php. This is done by the following filter function (note the filter priority, which is important here).
function custom_authenticate( $user, $username, $password ) { if ( is_wp_error( $user ) && isset( $_SERVER[ 'HTTP_REFERER' ] ) && !strpos( $_SERVER[ 'HTTP_REFERER' ], 'wp-admin' ) && !strpos( $_SERVER[ 'HTTP_REFERER' ], 'wp-login.php' ) ) { $referrer = $_SERVER[ 'HTTP_REFERER' ]; foreach ( $user->errors as $key => $error ) { if ( in_array( $key, array( 'empty_password', 'empty_username') ) ) { unset( $user->errors[ $key ] ); $user->errors[ 'custom_'.$key ] = $error; } } } return $user; } add_filter('authenticate','custom_authenticate', 31, 3);
Other ways?
I know of one alternative to the above code: Since wp_authenticate is a plugable function, you could simply overwrite it. But this you only can do with a plugin, so you have to add a plugin to your site and activate it, which I think is a bit more hassle.
Is there another way you know of? Please let me know in the comments.
Good stuff. Thanks for posting!
Handling empty logins was doing my head in. Thanks for the clarification!
God bless you! Finally a code that works! Googling thousands of sites searching for a solution to this never lead me to a solution before!