Monday, October 4, 2010

Grails console and LDAP via JNDI

Hi folks!

I've spent over 6 hours today fiddling with LDAP from Grails console and let me tell you it's been a huuuuge disappointment! Let me explain...

I'm using LDAP (it's Active Directory but this is not really relevant) to store users with their attributes. To perform authentication other than usually (having a user that has right to read the password attribute and then query LDAP once a user logs in, verify the password, etc.) I need to login in using credentials provided by user on login page.

With that the use of grails-springsecurity-ldap is pretty much toasted and a new implementation is needed. I don't want to get into any details of spring security plugin, because it makes no sense in this context. What makes a huge difference is the way we interact with LDAP in Java.

import javax.naming.*
import javax.naming.ldap.*

try {
LdapContext context = new InitialLdapContext((Hashtable) [
(Context.INITIAL_CONTEXT_FACTORY): "com.sun.jndi.ldap.LdapCtxFactory",
(Context.PROVIDER_URL) : "ldap://",
(Context.SECURITY_PRINCIPAL) : "DOMAIN\\invalid",
(Context.SECURITY_CREDENTIALS) : "invalid",
(Context.REFERRAL) : "follow",
(Context.BATCHSIZE) : "30"
], (Control[]) []);
println "Logged in!"
} catch (AuthenticationException e) {
println "NOT lOGGED IN"

The assumption here is of course that "DOMAIN\invalid" either does not exist or has a password other than "invalid" :)

What one would expect from this piece of code is that it tries to create the initial context and since the credentials are wrong an AuthenticationException is being thrown thus the message "NOT LOGGED IN" should appear.

Well, in Groovy console (you know, the one that you get when you install Groovy on your PC) works exactly this way but Grails console works differently. It creates the initial context without problems and presents one with "Logged in!" message.

Why is this happening? Well the CLI support stuff overrides all protocol handlers (and I mean EVERY SINGLE ONE) with Spring's org.springframework.mock.jndi.SimpleNamingContext! Grouse!

What I ended up doing was to use the LdapClient directly (even though it's an implementation detail it gave me all the methods I needed) and life is (sort of) good again...

Check the bug report here.

1 comment:

Matthias Hryniszak said...

At the end of the day I've used JLDAP from Novell. Let me tell you - it's one hell of an LDAP client! And no fricken warnings emerge from using the piece of crap that's inside the JDK! :D