Darren Mothersele

Software Developer

Warning: You are viewing old, legacy content. Kept for posterity. Information is out of date. Code samples probably don't work. My opinions have probably changed. Browse at your own risk.

Using an external data source for Drupal user authentication and login

May 15, 2008

web-dev

Update: This information is not applicable to Drupal 6. To use an external data source for authentication in Drupal 6 you need to use hook_form_alter to add your own validation function to the login form. The two functions below are intended as an outline of how it was done in Drupal 5. You only need these two hooks to extend the authentication - anything further than this will be specific to your requirements.

You can use any database table to validate users for your Drupal site. In this case I'm validating users against a database of clients. This client database is maintained outside of Drupal. It's a simple two step process, and just needs a couple of PHP functions in a custom module:

Step One: hook_auth() puts our own authentication code into the Drupal authentication process, we return true to validate a user, or false if the credentials don't match. If we have successfully authenticated someone then we also set a global variable that we can check in the next step.

Step Two: hook_user() allows us to put our own code into the user creation process. When a new user is authenticated Drupal will create a local user object for them. We hook into this process to fill in their details.

<?php
/**
* Implementation of hook_auth()
*/
function modulename_auth($username, $pass, $server) {
 
// Does username exist in our clients database?
 
$results = db_query("SELECT login, password FROM clients WHERE login = '%s' AND password = '%s'",$username,$pass);
 
$row1 = db_fetch_array($results);
  if (
$row1) {
     global
$modulename_authenticated;
    
$modulename_authenticated = TRUE;
     return
TRUE;
  }
  else {
     return
FALSE;
  }
}

/**
* Implementation of hook_user()
*/
function modulename_user($op, &$edit, &$account, $category = NULL) {
  switch(
$op) {
     case
'insert':
       
// a new user is being added; check if we did authentication,
       
global $modulename_authenticated;
        if (
$modulename_authenticated) {
         
$result = db_result(db_query("SELECT email FROM clients WHERE login = '%s'",$account->name));
         
// Set email address in the user table for this user
          // You might want to set up some other parts of the user record here too
         
db_query("UPDATE {users} SET mail = '%s', name = '%s' WHERE uid = %d", $result, $account->name, $account->uid);
        }
  }
}
?>

Update:

To create this as a module, you need two files:

modulename.info
modulename.module

You save these files in a folder called modulename somewhere within the Drupal module include path. For example in /sites/all/modules/modulename

The first of these files contains the basic module information. This can be as basic as this...

name = modulename
description = what your module does
package = Other

You then put the PHP code for the hooks you wish to implement into the *.module file. Hooks are documented on api.drupal.org. All your hooks start with the module name, as per the config file, and your filenames. For this example the content of the modulename.module file would be as follows:

<?php
/**
* Implementation of hook_auth()
*/
function modulename_auth($username, $pass, $server) {
// Does username exist in our clients database?
$results = db_query("SELECT login, password FROM clients WHERE login = '%s' AND password = '%s'",$username,$pass);
$row1 = db_fetch_array($results);
if (
$row1) {
global
$modulename_authenticated;
$modulename_authenticated = TRUE;
return
TRUE;
}
else {
return
FALSE;
}
}

/**
* Implementation of hook_user()
*/
function modulename_user($op, &$edit, &$account, $category = NULL) {
switch(
$op) {
case
'insert':
// a new user is being added; check if we did authentication,
global $modulename_authenticated;
if (
$modulename_authenticated) {
$result = db_result(db_query("SELECT email FROM clients WHERE login = '%s'",$account->name));
// Set email address in the user table for this user
// You might want to set up some other parts of the user record here too
db_query("UPDATE {users} SET mail = '%s', name = '%s' WHERE uid = %d", $result, $account->name, $account->uid);
}
}
}
?>

You will need to adapt the actual authentication code to match your requirements.

Update 2:

The normal login process will call your custom authentication when the built in login process fails.

The process is as follows:

External authentication involves firing the auth hook, and on success either validating an existing user or creating a new user object. When a user is created this way a record is stored in the authmap table that confirms which module validates this user login.