Spring authentication using ActiveDirectoryLdapAuthenticationProvider and embedded ldif

Tags: , , , ,



one of my clients requirement was to authenticate users against his corporate ActiveDirectory (LDAP). So I used standard ActiveDirectoryLdapAuthenticationProvider and it works like a charm.

@Bean
public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
    ActiveDirectoryLdapAuthenticationProvider adProvider = new ActiveDirectoryLdapAuthenticationProvider(
            ldapConfig.getLdapDomain(), ldapConfig.getLdapUrl(), ldapConfig.getLdapRoot());
    adProvider.setConvertSubErrorCodesToExceptions(true);
    adProvider.setUseAuthenticationRequestCredentials(true);
    adProvider.setSearchFilter(ldapConfig.getLdapSearchFilter());
    return adProvider;
}

Problem is that clients AC is hidden behind firewall. It works after deployment, but I cannot reach AC during local development due to cleints security policy. So, I had an idea that maybe for dev profile I will use embedded LDAP server (UnboundID LDAP SDK for Java). I’m not an LDAP expert, but I somehow composed simple ldif file, and it looks like this:

dn: dc=test,dc=local
objectclass: top
objectclass: domain
objectclass: extensibleObject
dc: test
# Organizational Units
dn: ou=groups,dc=test,dc=local
objectclass: top
objectclass: organizationalUnit
ou: groups
dn: ou=people,dc=test,dc=local
objectclass: top
objectclass: organizationalUnit
ou: people
# Users
dn: uid=john,ou=people,dc=test,dc=local
objectclass: top
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
cn: John Doe
sn: John
uid: john
password: johnspassword
# Create Groups
dn: cn=administrators,ou=groups,dc=test,dc=local
objectclass: top
objectclass: groupOfUniqueNames
cn: administrators
ou: administrator
uniqueMember: uid=john,ou=people,dc=test,dc=local

I also configured embedded ldap properties:

spring.ldap.embedded.base-dn=dc=test,dc=local
spring.ldap.embedded.ldif=classpath:localldapactivedirectory.ldif
spring.ldap.embedded.port=12345
spring.ldap.embedded.url=ldap://localhost:12345/
spring.ldap.embedded.validation.enabled=false

UnboundID had no problem with that, but as you guess I encounter problem during authentication:

[LDAP: error code 34 - Unable to parse bind DN 'john@test.local':  Unable to parse string 'john@test.local' as a DN because it does not have an equal sign after RDN attribute 'john@test.local'.]; nested exception is javax.naming.InvalidNameException: [LDAP: error code 34 - Unable to parse bind DN 'john@test.local':  Unable to parse string 'user_cms@test.com' as a DN because it does not have an equal sign after RDN attribute 'john@test.local'.]

To show you whole picture I add that error occurs during authentication attempt (in custom authentication service):

Authentication authentication = authenticationManagerBuilder.getObject()
            .authenticate(authenticationToken);

I presume that it is caused by the fact that my ldif file is too simple. It would work with vanilla Ldap authentication provider, but not with ActiveDirectoryLdapAuthenticationProvider.

Is there anyone who knows how to “mock” ActiveDirectory(LDAP) in ldif file so ActiveDirectoryLdapAuthenticationProvider could use it during authentication?

Answer

I had the same problem and found a solution that works, but I am not very happy with it. Here is how it works for me:

  1. Adjust the .ldif file

    Add the userPrincipalName attribute to your .ldif file and fill it with the same value as the dn, in your case:

    dn: uid=john,ou=people,dc=test,dc=local
    userPrincipalName: uid=john,ou=people,dc=test,dc=local
    
  2. Use the dn instead of the email address for authentication

    You use john@test.local in your test for authentication. To make it work, you have to use the dn: uid=john,ou=people,dc=test,dc=local

After these changes, the authentication against embedded LDAP worked in the tests. Better solutions are welcome!



Source: stackoverflow