Directory-based Authentication

This writeup discusses the best way to authenticate users in an LDAP environment.

I've taken the time to write this because I keep seeing programs written that cause integration problems due to design flaws.  I've seen this from companies small and large, commercial and opensource.  In each case, the programmers were attempting to get something working, and were somewhat successful.  But in each case, there was one or more design flaw that caused issues for those who attempted to use those products with existing directory servers.

The RIGHT way:

The right way is to integrate the application with direct LDAP support for authentication.  In this way, the LDAP server does the authentication through a standard set of steps that always work, regardless of the brand or version of LDAP server, the encryption technology used, directory tree structure, or any other criteria.

It's a straightforward process if you do it right; a simple 6 step process:
  1. Get login (or email) and password from user.
  2. Bind to the LDAP server anonymously (or using a service account if anonymous binds are disabled)
  3. Search the directory using an appropriate filter to identify the record for the specific login name provided.
  4. If one and only one entry is returned, that is the entry you want - get the DN of the entry. (If zero, or more than one entries are returned, return "no such user")
  5. Re-bind to the LDAP directory using the DN returned in step 4 and the password from step 1
  6. If the LDAP server allows the bind, the login is successful.  Otherwise, return "invalid password".
That's it.  It will work with any LDAP server out there, every time.

A sample Perl program using the steps above is free for download and use: ldap_auth_user

Various wrong ways:

Each of the following approaches will work in limited circumstances, but each is flawed.  I'll review them here to cover the design limitations of each.

Automatic determination of user's DN
This approach is similar to the "right" way in that the application passes the request to the back end LDAP server.  In this regard, it is good.  But this approach attempts to programmatically determine each user's DN so as to skip steps 2-4 above.   This is where the flaw lies, in that it ties the authentication of a particular user to their directory tree and to their RDN construction.   Such an implementation will break if one is using a directory tree other than the one envisioned by the programmer -- a sign of poor integration design.

Synchronization of password from LDAP into an application
Programs with this design attempt to synchronize a user's password from the LDAP directory into the application through some sort of periodic sync process.    There are several fundamental flaws with this approach:
  1. It requires that passwords be stored in cleartext (a security risk), or in some encryption scheme understood by both the LDAP server and the application)
  2. It assumes that passwords can be read from the source directory.  Most directory servers do not allow read access to user passwords by default.  And many LDAP servers do not allow configuration for read access at all.