Creating a custom login form in WordPress

There's a few reasons you might want to create your own login form in WordPress, perhaps you just want greater customisation of where the admin login area resides, or you might be creating your own custom client area that sits outside of the default wordpress CMS. This article looks at how you can do it. 

To create your own custom login form for WordPress you've essentially got two options, either you create your own form from scratch and write your own queries against the database (not particularly difficult using the wp_users table), or you can try and hook into the existing WordPress functionality to use some of the built in features. The latter is generally preferable for future compatability and to ensure you're doing all the right security checks that you can delegate to WordPress.

Creating a custom login form

The first step is nice an easy, all you need to do is use WordPress's built in wp_login_form function to generate all the markup for you like so:

$args = array(
    'echo'           => true,
    'redirect'       => site_url($_SERVER['REQUEST_URI']),
    'form_id'        => 'form-login',
    'label_username' => __( 'Username or Email address' ),
    'label_password' => __( 'Password' ),
    'label_remember' => __( 'Remember Me' ),
    'label_log_in'   => __( 'Sign In' ),
    'id_username'    => 'user_login',
    'id_password'    => 'user_pass',
    'id_remember'    => 'rememberme',
    'id_submit'      => 'wp-submit',
    'remember'       => true,
    'value_username' => NULL,
    'value_remember' => true );

wp_login_form( $args );

Place the above where you want to output your form, for example you could place this inside a login page template (e.g. titled login.php placed in the root of your theme folder):

<?php
/*
Template Name: Login
*/
get_header();

$args = array(
    'echo'           => true,
    'redirect'       => site_url($_SERVER['REQUEST_URI']),
    'form_id'        => 'form-login',
    'label_username' => __( 'Username or Email address' ),
    'label_password' => __( 'Password' ),
    'label_remember' => __( 'Remember Me' ),
    'label_log_in'   => __( 'Sign In' ),
    'id_username'    => 'user_login',
    'id_password'    => 'user_pass',
    'id_remember'    => 'rememberme',
    'id_submit'      => 'wp-submit',
    'remember'       => true,
    'value_username' => NULL,
    'value_remember' => true );

wp_login_form( $args );

get_footer();

Great, now we've got a form. In theory, all you need to do now is create a page in the WordPress CMS selecting your new login template and this in itself is enough to allow users to login... but there's one problem - as this form is still using the default WordPress functionality any redirects are going to end up back at the default login screen. Specifically, here are the other scenarios you may wish to deal with:

  • Login username or password is incorrect
  • Login fields are blank
  • Where to redirect non-admin users
  • Where to redirect on log out

As an extra, you may also want your users to be able to login with their email address as well as their username - we'll look at how to do this too. 

Login username or password is incorrect

For this section and all the below examples, you can place the code inside your functions.php, though I would strongly recommend placing the code inside a class as part of a plugin for maintainability. 

add_action( 'wp_login_failed', 'member_login_failed' );
public function member_login_failed( $user )
{
    $referrer = $_SERVER['HTTP_REFERER'];
    if (!empty($referrer) && !strstr($referrer, 'wp-login') && !strstr($referrer, 'wp-admin') && $user!=null )
    {
        if (!strstr($referrer, '?login=failed'))
        {
            if(!strstr($referrer, '?'))
            {
                $referrer .= '?';
            } 
            else 
            {
               $referrer .= '&';
            }

            wp_redirect($referrer . 'login=failed');
        }
        else
        {
            wp_redirect($referrer);
        }

        exit;
    }
}

Notice that we append a query string of login=failed so that back on our login form page we can output any errors for this.

Empty login fields redirect

The next snippet caters for empty login fields redirecting back to the default form:

add_action( 'authenticate',  $this, 'member_blank_login' );

public function member_blank_login( $user )
{
    $referrer = '';
    if( !empty( $_SERVER['HTTP_REFERER'] ) )
    {
       $referrer = $_SERVER['HTTP_REFERER'];
    }

    $error = false;

if(empty($_POST) || $_POST['log'] == '' || $_POST['pwd'] == '') { $error = true; } if (!empty($referrer) && !strstr($referrer,'wp-login') && !strstr($referrer,'wp-admin') && $error) { if (!strstr($referrer, '?login=failed') ) { wp_redirect( $referrer . '?login=failed' ); } else { wp_redirect( $referrer ); } exit; } }

Redirect non-admin users to a different section

If you're creating a client area that sits outside of the default CMS and you want to direct non-admin users to a different area of the site after successful login you can use the below:

add_filter( 'login_redirect', 'users_login_redirect', 10, 3 );
public function users_login_redirect($redirect_to, $request, $user)
{
    if( isset( $user->roles ) && is_array( $user->roles ))
    {
        return (in_array('administrator', $user->roles)) ? admin_url() : '/members';
    }
}

Logout Location

Use the following code to dicatate the logout location:

add_filter('logout_url', 'members_logout', 10, 2 );
public function members_logout($logout_url, $redirect)
{
    return $logout_url . '&redirect_to=' . urlencode( get_option('siteurl' ) );
}

Allow the email address to be used as the username

It's common functionality to allow users to login with their email address, this code snippet allows you to do this:

add_action( 'wp_authenticate', 'email_address_login' );
public function email_address_login($username)
{
    $user = get_user_by( 'email', $username );

if(!empty($user->user_login)) { $username = $user->user_login; } return $username; }

Catching errors

To wrap up, all you need to do is add some form of notification in the login template for when the login fails:

if( isset( $_GET['login'] )  && $_GET['login'] == 'failed' )
{
    echo "<div class='notification error'>Incorrect username or password </div>";
}

The combination of the above snippets should allow you to create your own login form and account for all the possible scenarios that might end up redirecting your users back to the standard WordPress login page.

Sign Up
comments powered by Disqus
Sign Up

Popular Tags

350x250

Need a web developer?

If you'd like to work with code synthesis on your next project get in touch via the contact page.