How to Integrate Drupal CMS with External Authentication Service
Azoft Blog How to Integrate Drupal CMS with External Authentication Service

How to Integrate Drupal CMS with External Authentication Service

By Alex Ilchuk on March 6, 2013

Many websites that we build here in Azoft PHP department have user registration. In most cases it's more than enough to use the accounting system provided by the CMS, but there might be special cases that require non-trivial solutions. Today I'd like to share with fellow PHP developers our experience working on such a project and describe how to integrate Drupal with an external authentication service.

System overview

We've been working on a Drupal-based event tracking system. The user account information is retrieved from a remote web service. There is an LMS (Learning Management System). Access to the event tracker should be provided to the existing users of the LMS.

Authentication logic

The authentication mechanism for getting access to the tracker is complicated and doesn't simply require entering a login name and a password. Instead, the user is taken to the tracker via a link in the LMS. The tracker redirects the user to a remote service with the secret passkey, where the user can authenticate himself. After a successful authentication, the remote service redirects the user back to the tracker together with an authentication token. Using the token, we can get the user data via the remote service API methods.

Tools and methods

The remote service is accessible by the means of SOAP messages. The service API is documented in a WSDL file which is provided by the client.

PHP includes a SOAP library that we used to access the service. In our implementation we made a wsdlHelper class for registration/authentication and getting user data. The class methods will be briefly described after the following sample of code.

 
?php
 class WsdlHelper {
     private static $wsdl = 'http://yourapi.wsdl'; // your wsdl file or url
     private static $credentials = array        // special parameters, depend on your API.
         'apiusername' =--> '123',
         'apipassword' => '1234'
     );
     
     private static $role = array(3 => 'broker');
     
     private static function doRequest($method, $params = array()) {
         $client = new SoapClient(self::$wsdl);
         return $client->$method(array_merge(self::$credentials, $params));
     }
     
     static function authorize($token) {
         global $user;
         
         $result = self::doRequest('firstMethod', array(
             'token' => $token
         ));
         if (!$result->valid) {
             return false;
         }
         
         // search user
         $query = db_query('SELECT uid FROM {profile_values} WHERE fid = 1 AND value = '.$result->userid);
         $uid = db_fetch_array($query);
         if ($uid) {
             $user = user_load(array('uid' =>$uid['uid']));
         } else {
             
             // register
             $user = user_save(null, array(
                 'name' => $result->username,
                 'pass' => md5(uniqid('rand', true).time()),
                 'mail' => $result->email,
                 'status' => 1,
                 'roles' => self::$role
             ));
             
             $profile = array(
                 'profile_course_stage_uid' => $result->userid,
                 'profile_firstname' => $result->firstname,
                 'profile_lastname' => $result->lastname
             );
             profile_save_profile($profile, $user, 'Personal information');
         }
         
         // authorize
         $tmp = null;
         user_authenticate_finalize($tmp);
     }
     
     static function getAccess($userId) {
         global $user;
         
         $result = self::doRequest('secondMethod', array(
             'userid' => $userId
         ));
         // This applicable only for this case.
         if ($result->success) {                              
              // fetching and parsing data.
                // put your fetching and parsing code here.
               $data = array($result->data, $result->data2);
                    $userData = unserialize($user->data);
                 $userData['course_stage'] = $data;
                 user_save($user, $userData);
         } else {
             return false;
         }
     }
 }
?
  • doRequest  base method to perform a SOAP query.
  • Authorize  handles user registration and authentication.
  • GetAccess  gets and stores user data for using them later in the system.

Drupal strictly forbids creating users with an arbitrary ID. But in our case, we'd like to associate the external user ID with the Drupal UID. To do that, we extended the user account table with an extra field course_stage_user_ID that stores external ID retrieved from the external storage. During the authentication, we first check if a user with the corresponding external ID exists. If the ID existence is confirmed, we simply take the UID and authenticate the user. Otherwise, user registration is initiated.

Our wsdlHelper implementation uses the Drupal API for user registration and authentication.

For this specific task, we had to refresh the user data locally. This is being done by calling GetAccess in hook_user() inside our custom external authentication module.

As a result, the whole system integrates with an external account storage and performs user registration, authentication and updating data in accordance with the user status.

This method of external authentication is applicable for many projects. Please note that, once again, Drupal flexibility lets us implement a non-standard solution. The above example proves the effectiveness of Drupal for unusual tasks, which we aim to solve here in Azoft on regular basis, while keeping in mind our customers' requirements.

VN:F [1.9.22_1171]
Rating: 5.0/5 (2 votes cast)
VN:F [1.9.22_1171]
Rating: +3 (from 3 votes)
How to Integrate Drupal CMS with External Authentication Service, 5.0 out of 5 based on 2 ratings



Request a Free Quote
 
 
 

Please enter the result and submit the form

Content created by Alex Ilchuk