wordpress authentication - redirect after incorrect login


[caption id="" align="alignright" width="300" caption="Image via Wikipedia"]The logo of the blogging software WordPress.[/caption]

Few days ago I had to deploy a simple wordpress installation for a project at @therumpusroom_ with my buddy @twentyrogersc. Super simple, yet it presented a little issue: having a personalized authentication form, displayed on a wordpress page, it was re-directing to the default login screen after specifying incorrect credentials. It came out that we needed to implement the whole authentication mechanism on a page, hence tweaking the simple post form to send data to itself instead of submitting to wp-login.php (which, btw is working fine if users provide the correct credentials, and also accept a redirect parameter to make users land on a pre-determined page).

Just for my records, I leave the code here, and I hope I could save some time to people who incur in the same problem. Here's my solution:

  1. from the dashboard create a page and give it a meaningful permalink, such as log-in
  2. create a php file and give it a name according to the wordpress convention: page-<permalink>.php (in my case: page-log-in.php)
  3. write the php code to perform the whole authentication (hence including password check and signon), this is my code:
    	// if user is logged in, redirect whereever you want
    	if (is_user_logged_in()) {
    		header('Location: '.get_option('siteurl').'/how-to');
    	// if this page is receiving post data
    	// means that someone has submitted the login form
    	if( isset( $_POST['log'] ) ) {
    		$incorrect_login = TRUE;
    		$log = trim( $_POST['log'] );
    		$pwd = trim( $_POST['pwd'] );
    		// check if username exists
    		if ( username_exists( $log ) ) {
    			// read user data
    			$user_data = get_userdatabylogin( $log );
    			// create the wp hasher to add some salt to the md5 hash
    			require_once( ABSPATH.'/wp-includes/class-phpass.php');
    			$wp_hasher = new PasswordHash( 8, TRUE );
    			// check that provided password is correct
    			$check_pwd = $wp_hasher->CheckPassword($pwd, $user_data->user_pass);
    			// if password is username + password are correct
    			// signon with wordpress function and redirect wherever you want
    			if( $check_pwd ) {
    				$credentials = array();
    				$credentials['user_login'] = $log;
    				$credentials['user_password'] = $pwd;
    				$credentials['remember'] = isset($_POST['rememberme']) ? TRUE : FALSE;
    				$user_data = wp_signon( $credentials, false );
    				header('Location: '.site_url('how-to'));
    			else {
    				// don't need to do anything here, just print some error message
    				// in the form below after checking the variable $incorrect_login
    	// and finally print the form, just be aware the action needs to go to "self",
    	// hence we're using echo site_url('log-in'); for it
    <?php get_header(); ?>
    	<h2>log in</h2>
    	<form action="<?php echo site_url('log-in'); ?>" method="post" id="login-form">
    		<label for="log">User</label>
    		<input type="text" name="log" id="log" class="text" value="<?php echo wp_specialchars(stripslashes($user_login), 1) ?>" size="20" />
    		<label for="pwd">Password</label>
    		<input type="password" name="pwd" id="pwd" class="text" size="20" />
    		<label for="rememberme"><input name="rememberme" id="rememberme" type="checkbox" checked="checked" value="forever" /> Remember me</label>
    		<input type="hidden" name="redirect_to" value="<?php echo get_option('siteurl'); ?>/how-to" />
    		<input type="submit" name="submit" value="log in" class="button" />
    	// incorrect credentials, print an error message
    	if( TRUE == $incorrect_login ) {
    		<div class="incorrect_login">Incorrect login details. Please confirm the fields and submit it again,
    		or <a href="<?php echo site_url('contact-us'); ?>">contact us</a> to obtain a set of credentials.</div>
    <?php get_footer(); ?>
  4. and finally load this php file where your wordpress theme lives, it's done!