views:

234

answers:

2

Hi all,

I'm currently implementing/configuring the LDAP authentication of a Java web application using Spring Security 3.0. I'm using Microsoft AD LDS as LDAP server and chose the Spring's BindAuthenticator. I found out that the authentication only works if the authenticated user is a member of the partition's Readers role. The BindAuthenticator tries to read the user's attributes after the authentication, which seems reasonable in scenarios where authorities are retrieved from the directory service.

Being new to LDAP and AD, is this an acceptable practise when the application is integrated in an existing AD structure? Can fine-tune an give the user dns only read permissions for their own attributes rather than adding them to the Reader group?

Thanks Thomas


Edit 3/8/2010: Here's what I ended up doing: I copied Spring's BindAuthenticator (the whole class) and changed the method bindWithDn() as below. Differences are marked with DIFF.

private DirContextOperations bindWithDn(String userDn, String username, String password) {
    BaseLdapPathContextSource ctxSource = (BaseLdapPathContextSource) getContextSource();
    DistinguishedName fullDn = new DistinguishedName(userDn);
    fullDn.prepend(ctxSource.getBaseLdapPath());

    logger.debug("Attempting to bind as " + fullDn);

    DirContext ctx = null;
    try {
        ctx = getContextSource().getContext(fullDn.toString(), password);
        // Check for password policy control
        PasswordPolicyControl ppolicy = PasswordPolicyControlExtractor.extractControl(ctx);

        // *DIFF* Attributes attrs = ctx.getAttributes(userDn, getUserAttributes());

        DirContextAdapter result = new DirContextAdapter(null, new DistinguishedName(userDn),  // *DIFF*
                ctxSource.getBaseLdapPath());

        if (ppolicy != null) {
            result.setAttributeValue(ppolicy.getID(), ppolicy);
        }

        return result;
    } catch (NamingException e) {
        // This will be thrown if an invalid user name is used and the method may
        // be called multiple times to try different names, so we trap the exception
        // unless a subclass wishes to implement more specialized behaviour.
        if ((e instanceof org.springframework.ldap.AuthenticationException)
                || (e instanceof org.springframework.ldap.OperationNotSupportedException)) {
            handleBindException(userDn, username, e);
        } else {
            throw e;
        }
    // *DIFF* } catch (javax.naming.NamingException e) {
    // *DIFF*     throw LdapUtils.convertLdapException(e);
    } finally {
        LdapUtils.closeContext(ctx);
    }

    return null;
}
+1  A: 

It makes sense to me, it sense the BindAuthenticator performs a LDAP bind "as" the authenticated user, and uses the LDAP to populate the user details object. I'm guessing that the LDAP server requires the user to have a role entitling them to read their own attributes.

Did you try restricting the set of attributes (via setUserAttributes) to only a few attributes. I think in AD you can put RBAC on individual attributes, so you may be reading one attribute which has the 'Reader' role protection and some others that are unprotected.

Your other options would be:

  • Changing RBAC on the LDAP server like you suggest, but I don't have a prescription for you.
  • use a different authentication method which performs a bind as a generic server principal and reads the attributes. You might still need to bind as the user in order to check their password.
Justin
Thanks Justin. I'm not querying any attributes at all right now. Also already thought about creating a customised BindAuthenticator that doesn't read the attributes, but before doing so I was interested if it's a common behaviour that a bound user reads its own attributes.
Thomas
A: 

May you show us your final solution? May you paste the code or new clases?

Esteve Camps
Sure. Added my solution to the question. Hope that helps.
Thomas