LDAP Support? You must be joking!
I wish I understood why LDAP support is so unbelievably piss-poor in so many software products. So many organisations use LDAP as their core user directory (whether OpenLDAP, Active Directory or some other LDAP implementation) or have a directory service that will provide its data via an LDAP interface. I see people screaming for LDAP support in everything, but so little support from software coders/vendors; I can only assume because they personally don’t have much LDAP experience. Just about every F/OSS software project claims to have LDAP support, but because someone who didn’t totally understand the application itself wrote some add-on code to make it work. This leaves everyone else following poor instructions for adding-in support to an application that really should be supporting LDAP natively from day one.
For Request Tracker from BestPractical, I ended up re-writing the very limited user-contributed code that already existed into a fully-fledged extension for LDAP support. But it’s still not easy for RT administrators because my extension is not part of the core RT code; it is tacked-on over the top and, while I try to make it as easy as possible, people still run into problems with implementation. Also, when they need new features and I don’t have the time to implement them (which I don’t), they’re left up the creek with no paddle because the core development team didn’t write it and don’t intend to pick it up and code new features into it. In the case of RT, there is the suggestion that the LDAP code will be integrated into the next big version (RT4), but it is literally years too late.
At the moment I am having intense headaches over Foswiki, the fork of TWiki. This is the type of system that was born for use in organisations with existing user databases, but still getting it to take its user information out of LDAP is a NIGHTMARE. The basic principle is simple: have some perl code do an LDAP bind when a user tries to login, and if successful, do a search on their information and then map that information into the application based on a simple variable map. It’s how LDAP works in every app I’ve ever come across. But, to get this working in Foswiki you have to install four extensions (LdapContrib, LdapNgPlugin, GluePlugin & NewUserPlugin), you have to go through activating and configuring each plugin, and telling the login system which one of the three (confusing and not well documented) options it should use for each of the processes, then you have to go into the Wiki pages themselves and start again. You have to write (in a special Wiki code you won’t be familiar with) your own templates for gathering the LDAP information and then code up how you’re going to pass this to the NewUserPlugin so that during auto-registration some magical process can take place to update the user’s information. And I’m willing to bet that if I want the information to stay up to date with the LDAP database I will need a fifth plugin to check for changes during login as Login doesn’t normally handle user information, that’s a registration thing.
It’s the same all over. Pick pretty much any F/OSS web-app you like that requires a user database and you will find that LDAP support is either not-present, tacked on haphazardly, or is available only via user-contributed code of varying quality and documentation.
When you design an application like these, your user authentication and information systems need to be able to handle an LDAP (or sql for that matter) back-end. It’s really not difficult. In most languages the template code for the ldap searches and binds has been done for you, you just have to use it. I do what I can to provide good code to help people get LDAP working in their apps but it is not easy and there’s only one of me.
LDAP is easy, but each individual application has its own way of doing user authentication. If I want to put LDAP code into an app, it means I have to understand the nuances of the code and then write around it. In systems such as RT and Foswiki, the authentication systems are so complex it can take weeks to get up to speed with how they work, even with direct input from the developers themselves. I just don’t have the time to learn every authentication system ever written. If the developers themselves took a moment to realise how simple it is to add LDAP support to code they already understand, and then to get off their arses and *do* it, life would be a lot easier for everyone and it wouldn’t be so hard to implement these systems in company networks. That means we could finally start pulling away from “pay someone else to do it” mentality that has companies throwing thousands of pounds at piss-poor software vendors just to save from spending the time working out how to do it themselves.

IMNSHO, the application should not be doing this, ever. The application should know how to query the OS for AAA. The OS can then query LDAP, Kerberos, /etc/passwd, NIS or anything else as it needs to. Further, by doing it that way, the poor sods who have to maintain the server and it’s applications only need to look at one place when people complain of not being able to authenticate, instead of the willy-nilly “figure out which authentication source is used by the application in question, then track down it’s configuration information…” methodology used today.
Personally, I think Apache gets it wrong. It should only have one authentication module which, in turn, queries the OS for authentication information. Sure, everyone wants to be able to manage users with a simple file and not have them created in whatever the server uses for AAA (with appropriate no-login bits set), but even that’s only the result of having the ability to do it the super-easy way since (mostly) day one of the web server era.
You wrote, “LDAP is easy, but each individual application has its own way of doing user authentication.” And *that* is the heart of the problem. For LDAP you can substitute “text files”, “NIS”, “Kerberos”, “database-based”, etc, and be equally correct. The problem isn’t “application developers are doing a poor job writing AAA code” at all The problem is that AAA should *always* be passed off to the OS. Just this once, let’s stop re-inventing the wheel, OK?
I have to disagree, you can’t always just throw it at the OS. The simplest explanation is that the OS doesn’t always need, or indeed want, to know about your web-app’s user database. While the system may have a number of local users, you may need to run a virtual user environment. For example, there are a number of FTP servers such as vsftpd that pass authentication off to the OS by using getpwent to query the local passwd information, but it means that every vsftpd user has to be a system user. In the best case it is less than clean, in the worst case it’s a downright security problem. The same can be said of sharing the databases. If there’s a security hole in your web application, you could well find it’s a complete open door for anyone trying to break in to the rest of your system.
I think you need to take a step back and realise that, there already *is* the mechanism you describe, but it’s not housed in the core of the OS, but instead is run a daemon. I’m talking, of course, about SASL.
I agree that it is possibly in the interests of web-app developers to provide authentication mechanisms that use SASL, it is not entirely relevant. Nearly all F/OSS enterprise web-apps already have their own authentication mechanism with its own security paradigm. This means a framework already exists to which adding an LDAP mechanism is a piece of cake. It’s just a matter of a subroutine or two which, to a developer creating an enterprise app is no great leap.
In fact, to ask them to do the same with an authentication framework such as SASL is a harder task because the coding itself is harder to do as less model code already exists.
As well as the above, there is another reason why LDAP is so popular; it is not just an authentication system, in fact authentication is only a sub-section. It is in fact an information repository. It can be used to store pretty much anything you like in the same way as an SQL database can. In real terms this means that you can store not only your user’s name and password, but you can also store all of their other personal details, pictures and all kinds of web-app state information.
I by no means think that web-apps should default to LDAP operation, but it is so simple to provide LDAP as an option that I think more time should be invested in doing so. Primarily because, as I said in the original post, adding an authentication mechanism as an outsider can be difficult for the sole reason that you are not familiar with the authentication and security code in the app. But for the original developer, who understands the authentication system he wrote better than anyone else, adding in a getLdapAuth() or getLdapInfo() subroutine can be a pretty simple task.
What the developer gets out of this is the possibility of a much bigger user space and much more enterprise users who very often have SQL and LDAP databases already that they want to integrate with. As soon as you have enterprise customers on board, you have a basis for making some money too by selling installation support, adminstration support, and even custom code development services.
You are right that it would be useful to have a central system for this type of work, but PAM is not universal (or even close), SASL is an authentication mechanism not an information repository and that leaves you with three options: SQL, LDAP or write your own custom interface.
I know which I’d pick.