On my ActiveDirectory (AD) node.js plugin, a user requested support for LDAP referrals and chasing (#8). Unfortunately, I didn’t have access to a partitioned AD installation to test this.

The user wasn’t very helpful with giving me additional information or test scenarios to work with it so I took it upon myself to install a partitioned AD environment… as well as some heavy reading about how Microsoft implemented their referrals and partitioning. I probably still don’t understand it…

The one interesting thing is that by default they create two application partitions, one for DNS entries (Forest & Domain) and one for configuration which allows for these areas to be replicated. Those example referrals look like the following, although replace domain.com with your context.

  • ldap://ForestDnsZones.domain.com/dc=domain,dc=com
  • ldap://DomainDnsZones.domain.com/dc=domain,dc=com
  • ldap://dc.domain.com/CN=Configuration,dc=domain,dc=com

With referral chasing, you end up basically sending a request to each of the referrals with the same original query in order to get “everything”. So that one LDAP query can quickly lead to an “N+1” select problem, overhead on the network and slower responses. To get around the problem, I just created a couple of regular expressions to exclude and ignore those referrals.

var defaultReferrals = {
  enabled: false,
  // Active directory returns the following partitions as default referrals which we don't want to follow
  exclude: [
    'ldaps?://ForestDnsZones\\..*/.*',
    'ldaps?://DomainDnsZones\\..*/.*',
    'ldaps?://.*/CN=Configuration,.*'
  ]
};

The other way around this problem is to use the Global Catalog (GC) instead of direct LDAP queries. Essentially the GC just listens on a different port (3268) but any LDAP search requests will be for the entire “forest”.

I’ve published my Active Directory authentication (AuthN) and authorization (AuthZ) module for node.js. This module supports large active directory installation where over 1000 entries may be returned from a query via range specifiers. In addition, the module will recursively enumerate and expand all nested users and groups.

You can view or checkout the code online on my github account:

Installation is easy with npm:

npm install activedirectory

Usage is pretty simple:

var ad = new ActiveDirectory('ldap://yourdomain.com', 'dc=yourdomain,dc=com', 'authuser@domain.com', 'authpassword');
var username = 'bob@domain.com';
ad.findUser(username, function(err, user) {
  if (err) {
    console.log('ERROR: ' +JSON.stringify(err));
    return;
  }

  if (! user) console.log('User: ' + username + ' not found.');
  else console.log(JSON.stringify(user));
});

Hope you find it useful!