Three years ago, Kohsuke Kawaguchi, the man behind the Hudson/Jenkins continuous integration system, wrote two excellent blog posts (January 2008 and June 2008) on the absence of a good API for accessing Active Directory (AD) directly with Java. Kohsuke laid out the terrain, briefly described how he tackled the problem in the Hudson AD plugin and even gave advice on how an API could rectify the problem. I’m here to report that, after doing some research on the same topic recently, the situation has not improved. In fact, it’s a little worse.
In this post I’m just expounding on the research I did recently with trying to connect to AD from Java. The problem I was trying to solve was to simply authenticate a user against an AD domain and check their membership in a group.
LDAP vs. Talking to AD Directly
In Java, there really is only one widely available solution for communicating with AD: LDAP. Kohsuke wisely explains that Java cowers from connecting to proprietary systems such as AD in the name of portability. That’s generally a good thing, but it’s problematic if you want to solve a simple, constrained problem like mine. LDAP adds a thick layer of abstraction over a directory service that swallows up familiar AD terms like “groups”. Instead of being able to speak about a user’s group, with LDAP you have only generic attributes. Rather than just authenticating a user, LDAP forces a three step process that includes two, yes two, sets of user credentials.
The most cumbersome part of this process in Java is at the top of the trio of abstraction layers, the API for communicating with an LDAP compliant directory service. The Java Naming Directory Interface (JNDI) is the API built-in to Java SE for communicating with a directory service that speaks LDAP.
Here’s where the story turns really grim. There are three options for working with AD in Java: the Java SE JNDI API, one of the open source LDAP APIs written in Java, or Kohsuke’s proposed solution. Presumably since Java SE has had a decent LDAP API for so long, there are very few other Java APIs out there. Of those that exist today, it seems that all of them are now defunct projects. Even worse, I could only find one API that works specifically with AD. Kohsuke describes his solution in his blog post, but it has problems as well.
In reality, using JNDI is not all that bad. And that is probably why there aren’t many other options. JNDI is very flexible, portable and can work with LDAP, which is ubiquitous. There’s also really good documentation on how to use it. The common critique of JNDI is that you have to write a lot of boiler-plate code. If you want an easy-to-use API for simple tasks, you’re stuck either writing your own or using one of the poor options below. As far as I could tell, people haven’t written much on JNDI since around 2004 or 2005, which means to me that people have resigned to using it as is.
Open Source LDAP APIs
Don’t get me wrong, the usual suspects in the Java Open Source space, Apache and Sun (now Oracle), both have APIs. However, they are in states that are not typical for these normally excellent contributors.
The best LDAP API for Java that I’ve found is Oracle’s OpenDS. OpenDS is actually an Open Source directory server project that was started by Sun, but includes a very nice SDK for working with LDAP. The SDK is robust and well written and this was the solution I ended up choosing. However, it appears that Oracle has pulled the plug on the project. The “downloads” link on the SDK homepage links to a page on the new java.net site here. As of 2/17/2011 is just a message stating that the page could not be found. A fellow WordPress blogger offers consensus that the OpenDS “Product has been discontinued. Oracle may offer commercial and supported products based on OpenDS in the future ”. If you just need some decent Java code to connect to an AD server though, it shouldn’t be a big deal to just find a jar for the OpenDS SDK and use it.
A company named ForgeRock has forked the OpenDS code and is offering similar services to what I assume Sun was previously offering. The new open source product is named OpenDJ, which ForgeRock claims will “meet Sun’s original product roadmap for OpenDS”. However, right now the offering is only the directory service server. I poked around on the site and couldn’t find an LDAP API download like OpenDS provided. The only download is for the entire server and doesn’t contain any LDAP API jars, as far as I could tell. I did find that ForgeRock has plans to release a stand-alone API soon though. Their roadmap on their wiki states that OpenDJ 2.5, which is scheduled for a Q1 2011 release, will have a “New LDAP Client SDK”.
Thanks to jhawk28 on Hacker News for the tip.
Apache LDAP API
Apache offers what is merely an “experimental” API. From a cursory look, it appears to be similar to the OpenDS SDK. The cool thing about Apache’s library is that they have a Java and a Groovy interface. This is something to watch for in the future, but I chose to stay clear of such a new offering, in case it goes defunct. The other down side is that there is scant documentation available on the API.
Spring LDAP (Added on 2/23/2011)
The venerable Spring framework provides an LDAP solution as well. I did research this one a bit in my search, but had to reject it without trying it out. The main problem with Spring LDAP is that it has a lot of baggage. You have to have the entire core Spring framework in your classpath in order to use Spring LDAP. Since my application doesn’t use Spring, I didn’t want to add all that excess (and confuse other developers along the way, keep it up-to-date, etc…).
I can only speculate on another major problem. I’m guessing, that like the other API’s Spring LDAP has it’s own abstraction of the already abstract LDAP. So this doesn’t get you any closer to just working with AD. You have to try it out to see for yourself, but that’s my guess. Aside from that, I’m also guessing that it’s quite a nice API, since Spring tends to be so popular amongst enterprise Java development teams.
Novell has a Java API that seems to have been popular once, although largely unusable now. The only working link I can find now is to a site that has jldap usage samples. The “Sample Home” and “Sample Information” links lead to a newer Novell developer site that doesn’t have anything about jldap there. I was able to find a link to the jldap CVS repository and download the source from there. You’ll see though that the code has not been touched in years. It’s also impossible to determine which branch has the most recent code. I tried to compile several branches, all with no luck. I searched around and found that you need a proprietary jar file that you get from some Novell product in order to compile it. I’d actually be surprised if the code would still compile, even if I could get the missing jar. It’s pretty clear that this project is not supported anymore and probably not worth the time to investigate.
All the Rest
There are some others listed on this page at the Apache LDAP API site. There’s some overlap with this list. To the best of my knowledge, the combination of this list and Apache’s is the entirety of Open Source LDAP API offerings in Java.
I could only find a single active proprietary API for Java. Jespa, is a Java library that actually works directly with AD through the NTLM protocol, rather than using LDAP. I checked this library out and it’s very convenient. In fact, the API is just what I was looking for. I can call a simple authenticate method with a user name and password supplied and then check for group membership just as easily. The library seemed to do a good job of using AD specific terminology so it made the code read well. I found Jespa mentioned in several forums and postings on the net as the recommended way of solving my specific problem. In fact, there is even a Spring framework plugin for AD that is based on Jespa.
The problem with Jespa is it’s not free and it’s website is poorly designed. I work for a very profitable corporation, so the license fee is not a real problem. But, if they’re going to pay, they need to feel like they’re working with a professional company. Jespa’s website houses so little information about the company that produces it, Ioplex, that my company was not comfortable buying a license from them. There is a phone number listed, but no company information page and no street address. There’s also very little support information provided. I know that seems trite of us, but actually, it’s patently unprofessional to sell services without making potential customers feel safe in working with you.
This one is the germ of a quite sane way to talk to AD directly from Java. Basically, Kohsuke is using one of his own open source projects, com4j, to allow Java to talk to Windows native COM objects. This way you are interacting directly with AD. The main advantage, as Kohsuke points out several times, is that it can be made into a zero configuration solution. With LDAP you have to know and store an AD user/password that has enough authority to connect and read the directory just to be able to authenticate someone. With Kohsuke’s solution, you can just authenticate the person in one call (notice that Jespa does the same thing, although via NTLM).
Kohsuke’s solution isn’t packaged as an API, but it’s simple and described good enough in his blog entries (see above). Even better, he’s implemented a solution in the Hudson AD plugin, which is open source. I checked out the source and it was simple and easy to understand. The only problem here is the com4j project. It appears to be active on java.net, but there are no downloads available. So if you want a jar file for it you’ll have to dig it up. This link on java.net does provide the URL for the Subversion repository however, so you should be able to check it out and compile it into a jar.
If you’re looking for a simple, recent and well maintained Java solution to working intuitively with Active Directory, you’re out-of-luck. The only viable open soruce solution, OpenDS, has just been dropped by Oracle and the only decent licensed one, Jespa, is a little too shady and unknown to risk. Kohsuke railed three years ago about the bad situation in hopes that it would improve – it hasn’t.I don’t claim that I did exhaustive research here, so if I’ve missed an important library or resource, please post it in the comments. If I have time, I will evaluate it and update this