Wordpress-custom authentication (LDAP, Crowd, OpenID, Restful Service, Gmail, Facebook or social network...)

Wordpress-custom authentication (LDAP, Crowd, OpenID, Restful Service, Gmail, Facebook or social network...)

Posted: 10 years ago in  PHP | Wordpress |


Wordpress has its own authentication and authorization, of course :-) However, we also have own strong, reliable authentication system, or we may call SSO software. It would be greate if staffs can use one credentials from SSO system to login multi service such as email, CRM, Project Management system...etc, including wordpress.


Wordpress has its own authentication and authorization, of course :-) However, we also have own strong, reliable authentication system, or we may call SSO software. It would be greate if staffs can use one credentials from SSO system to login multi service such as email, CRM, Project Management system...etc, including wordpress.

Here is solution, we intercept the authentication process, send username and password to SSO System and get the user information. If the user does not exist in wordpress database, we create new user with information we get from SSO System.
In Wordpress, to intercept, we use hooks. There are two types: filter and action (using functions add_filter and add_action). add_filter match our situation.
In case you wonder about filter and action, here is quote from codex documentation:

Actions are triggered by specific events that take place in WordPress, such as publishing a post, changing themes, or displaying a page of the admin panel. Your plugin can respond to the event by executing a PHP function, which might do one or more of the following:

Modify database data / Send an email message / Modify what is displayed in the browser screen (admin or end-user)

Filters are functions that WordPress passes data through, at certain points in execution, just before taking some action with the data (such as adding it to the database or sending it to the browser screen). Filters sit between the database and the browser (when WordPress is generating pages), and between the browser and the database (when WordPress is adding new posts and comments to the database);

Code Customization

Go to active wordpress theme's folder, edit functions.php in wp-content/themes/theme-name/ (if file does not exist, just create new one). Then, put these code at very end of file

add_filter( 'authenticate', 'custom_validation', 10, 3 );

function custom_validation( $user, $username, $password ){
    if($username == '' || $password == '') return;

    // Get authentication result from external source
    $is_authenticated = getCredentialFromExternalSSOSystem($username, $password);
    
    
    if( $is_authenticated == False ) {
        // Incorrect authentication, send back an error message
        $user = new WP_Error( 'denied', __("<strong>ERROR</strong>: User/pass bad") ); 
    } else if( $is_authenticated ) {
        // These data supposed to sent from SSO System, here I create the fake data. You may get it in form of JSON/XML then parse it
        // Fake data
        $ext_auth = array(
            "email" => "user@gmail.com",
            "first_name" => "Lastname",
            "last_name" => "Firstname",
            "username" => "username",
            "userpass" => "password"
        );
        
        $userobj = new WP_User();
        // Check if there is user in wordpress with same email
        $user = $userobj->get_data_by( 'email', $ext_auth['email'] ); 
        // Does not return a WP_User object
        // Attempt to load up the user with ID
        $user = new WP_User($user->ID); // Attempt to load up the user with that ID
        
        if( $user->ID == 0 ) {
            // The user does not currently exist in the WordPress user table.
                       
            // If you do not want to add new users to WordPress if they do not already exist, then uncomment the following line and remove "user creation code"
            //$user = new WP_Error( 'denied', __("<strong>ERROR</strong>: Not a valid user for this system") );
            
            // User Creation Code
            // Setup the minimum required user information to create a user in wordpress system
            $userdata = array(
            'user_email' => $ext_auth['email'],
            'user_login' => $ext_auth['username'],
            'user_pass' => $ext_auth['userpass'],
            'first_name' => $ext_auth['first_name'],
            'last_name' => $ext_auth['last_name']
            );
            $new_user_id = wp_insert_user($userdata); // A new user has been created
             
            // Load the new user info
            $user = new WP_User($new_user_id);
        }
    }
    //This code will stop the authentication procedure or the procedure will continue and try with normal wordpress authentication before return failure notification to end-users
    //Think about authentication as layers, wordpress authentication is the last one
    remove_action('authenticate', 'wp_authenticate_username_password', 20);

    return $user;   
}

Code Explanation:

This line will intercept the authentication

add_filter( 'authenticate', 'custom_validation', 10, 3 );

This line will....well, you tell me :roll:

if($username == '' || $password == '') return;

In this example, I used the fake data array to create new user if the authentication is failed. Actually, those are fetched from SSO System. Will be update another example of how to communicate with other SSO System such as OpenID, Facebook, etc...