Active Directory in Drupal

So I was at work and I came across a new challenge. I needed to make a listing of all the current undergraduate students in our department inside a Drupal page. The list needed to have first and last names, needed to be sorted alphabetically, and needed to include a link to the student’s personal webpage, if they had it enabled. Unfortunately not everyone in the department has an account on our Drupal site (it’s optional).

Since our students with Drupal accounts already had profile information set up, I could just check whether that “Show Personal Webpage” flag was 1 or 0. Our department runs an Active Directory server that contains all the student’s information, so I wrote a script that connects and binds to the server, pulls down the pertinent information, and then displays the results.

This is an example of how to perform Active Directory searches in the context of Drupal, using PHP’s LDAP library.

Configure LDAP Options

The very first thing we need to do is configure the options for PHP’s ldap_search method.

$ldaprdn  = 'account_name_for_searching';
$ldappass = 'password_for_account';
$ldapserver = "server_address_here";
$dn = "base_dn_for_server";
$attributes = array("displayname", "sn", "name");
$filter = "you_ldap_filter";

$ldaprdn – A valid AD account that can run searches against the tree.
$ldappass – The password for that account.
$ldapserver – The address of the server.
$dn – The base dn for the tree.
$attributes – An array of the attributes you want to retrieve. This example gets “displayname”, “sn”, and “name”.
$filter – A valid LDAP filter. This part is optional.

Connect to AD and Search

Now that we have the script configured, we need to do three specific steps in order to get the results we want. First, we need to establish a connection to the server. Second, we need to bind to the server using a simple-authentication method. Third, we need to actually perform the LDAP search and retrieve the results.

// First we try to establish a connection.
$ldapconn = ldap_connect($ldapserver) or die("Could not connect to " . $ldapserver . "!");

// If a connection is established...
if ($ldapconn) {

// This sets the right LDAP protocol version
ldap_set_option($ldapconn, LDAP_OPT_PROTOCOL_VERSION, 3);
// This disables recursive searchs through the tree; Active Directory doesn't like those.
ldap_set_option($ldapconn, LDAP_OPT_REFERRALS, 0);

// Attempt to bind with the server.
$ldapbind = ldap_bind($ldapconn, $ldaprdn, $ldappass);

// If we successfully bind...
if ($ldapbind)
{
// Perform the search and get the results.
$result = ldap_search($ldapconn, $dn, $filter, $attributes);
// Convert the results into an array of LDAP entries.
$entries = ldap_get_entries($ldapconn, $result);

}
else
{
echo "LDAP bind failed to " . $ldapserver . "!";
}
// Close the connection to LDAP, we don't need it anymore
ldap_unbind($ldapconn);

A very import step is to set the LDAP options correctly. Note that you must be connected to the server in order to set the options. Now that we have the LDAP results stored in a variable, we can do all sorts of things with it. I’ll just show you an example of a few things that I do with them.

Do Stuff with the Results

You can do a lot of stuff with the results. In this example, we will sort the users by last name alphabetically, using a case-insensitive search. Then we will check to see if each user has a custom Drupal Profile setting set, and then print out their name and whether they have chosen to display their personal web page (the profile setting).

// Sorts the entries by sn (sir name), from A-Z.
foreach ($entries as $key => $row)
{
  // We make a new array of just sn's,
  // which will be used as an argument
  // to sort the $entries array by.
  $sn[$key] = $row['sn'];
  // Force everything to lowercase,
  // this gives us a case-insensitive ordering.
  $sn[$key][0] = strtolower($sn[$key][0]);
}
// Using the array $sn as an argument,
// sort in ascending order the array $entries.
array_multisort($sn, SORT_ASC, $entries);

// Now we print out the results.
for ($i = 0; $i < $entries["count"]; $i++)
{
  // Get the current name ("jsmith") and
  //display name ("John Smith")from the LDAP entries.
  $name = $entries[$i]["name"][0];
  $displayname = strtolower($entries[$i]["displayname"][0]);

  // Do a Drupal database lookup for that name.
  // This will either return the uid or FALSE
  $uid = db_result(db_query("SELECT uid FROM {users} WHERE name = '%s'", $name));

  // If a valid uid is returned, load the user
  if($uid)
  {
    $account = user_load(array('uid' => $uid));
  }

  // Now check to see if they have the
  // "Show Personal Webpage" profile option enabled.
  if ($account->profile_show_webpage == '1')
  {
    // If they do, print out their name as a link
    print "<a href=\"#\">";
    print $displayname;
    print "</a>";
    unset($account);
  }
  else
  {
    // Otherwise just print their name.
    print $displayname;
  }
}
}
?>  

This code can be embedded anywhere in a Drupal node, provided the input method is set to Full PHP Code. Just put these three code snippets into any page, surrounded by proper tags. Please note that this will make an Active Directory connection, bind, and search every time the page is loaded, so it may not be the best idea if you have a large amount of users. Consider caching the data to ease the load on your AD server.