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:
- Get login (or email) and password from user.
- Bind to the LDAP server anonymously (or using a service account
if anonymous binds are disabled)
- Search the directory using an appropriate filter to identify the
record for the specific login name provided.
- 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")
- Re-bind to the LDAP directory using the DN returned in step 4 and
the password from step 1
- 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:
- 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)
- 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.