Custom Authentication

Integration of WordPress into other pre-existing systems and the ability to amalgamate it with other applications to provide better functionality is a good way to utilise the strengths of WordPress without having to migrate your whole site across to it. A key stepping stone to this merger is the authentication system.

The capabilities this control can add allows for you to either add more possible authentication mechanisms on top of the standard WordPress user management, or you can strip away the authentication against the WordPress database and just use an external system to handle your users.

Overview

This capability revolves around the authenticate filter provided in WordPress to process the login and a selection of other filters to hook into related functions allowing integration of logging out, registration and lost passwords.

Breakdown

Login/Logout

The main hook to utilise the the authenticate filter.  This triggers on login and allows you to check the users credentials against your proprietary service and return a valid user.  A problem with this is in general is that the user has to exist within WordPress, although this is not explicitly an issue as you can create them if they do not already exist it is an unnecessary extra step.  This problem occurs because it is complex to create a WP_User object from scratch rather than selecting it from the database.

Let’s look at an example:


add_filter('authenticate',  'authenticate_username_password', 20, 3);
function authenticate_username_password( $user, $username, $password ){
 // If a previous hook has successfully logged the user in, do not process further
 if ( is_a( $user, 'WP_User' ) )return $user;

 // Ensure details have been entered
 if ( empty( $username ) || empty( $password ) ){
  $error = new WP_Error();

  if( empty( $username ) )
   $error->add( 'empty_username', __( '<strong>ERROR</strong>: The username field is empty.' ) );
  if( empty( $password ) )
   $error->add( 'empty_password', __( '<strong>ERROR</strong>: The password field is empty.' ) );

  return $error;
 }

 // Attempt to authenticate user
 $success = check_username_password( $username, $password );

 // If unsuccessful return an error
 if( !$success )
  return new WP_Error(
   'invalid_username',
   sprintf( __( '<strong>ERROR</strong>: Invalid username. <a href="%s" title="Password Lost and Found">Lost your password</a>?' ),
    site_url( 'wp-login.php?action=lostpassword', 'login' )
   )
  );

 // Check if user exists, if not create with a random password
 $user_id = username_exists( $username );
 if( !$user_id ) {
  $random_password = wp_generate_password( 18, false );
  $user_id = wp_create_user( $username, $random_password );
 }

 // Return valid user object
 $user = get_user_by( 'id', $user_id );
 return $user;
}

While this will successfully authenticate logins using your proprietary system, it will still allow logins of users set up in WordPress, if you wish to stop this too you can just remove the default authentication filter:

remove_filter('authenticate', 'wp_authenticate_username_password', 20, 3);

This will now process login attempts through the proprietary system.

If your other system needs you to drop a cookie to mark that they’ve successfully logged in so that logging in to one system also works with the other you can create the cookie in the above function when the login is successful.  This means that once they log out of WordPress you will also need to remove this cookie, this can be done with the wp_logout action.

add_action( 'wp_logout', 'logout' );

function logout(){
 //Process logout here
}

Signup

The next step is being able to capture the registration of a user within WordPress and then register that user in your proprietary system, for this the user_register hook is useful.

This hook receives one parameter containing the ID of the user created in WordPress that you can use to get the username and the password is still available via the request.

add_action( 'user_register', 'register', 20, 1 );
function register( $id ){

 $user_data = get_user_by( 'id', $id );
 $username = $user_data['user_login'];
 $password = $_POST['password'];

//Ensure your system applies appropriate sanitization to the password
create_new_user( $username, $password );
}

Password Recovery

The WordPress password recovery system can be utilised too just catching it at the last step so that the new password is sent to the proprietary system hence appearing as a seamless integration.

add_action( 'password_reset', 'reset', 20, 2 );
function reset( $user, $new_pass ){

 reset_user_password( $user['user_login'], $new_pass );

}

Summary

In these short snippets it allows you to hook into all of the WordPress system and send triggers to your proprietary system allowing for a completely integrated overall experience by the user.