javaldapaemapacheds

Programmatically Authenticate LDAP user in AEM


I've set up local LDAP server Created user and group. Configured LDAP in AEM config manager and synchronized the users and group.

Using, ExternalIdentityProvider as a service reference, I'm able to get list of LDAP users I.e. I am able to validate if the user is present in LDAP or not.

But, I'm not able to validate user credentials using authentic method of the above mentioned API.

Am I missing any configuration specifics or the approach that I'm using is wrong ?

Updated:

Authentication code:

@Reference
private ExternalIdentityProviderManager externalIdentityProviderManager;

final String externalId = request.getParameter("externalId");
final String externalPassword = request.getParameter("externalPassword");

final ExternalIdentityProvider idap = externalIdentityProviderManager.getProvider("ldap");
final SimpleCredentials credentials = new SimpleCredentials(externalId, externalPassword.toCharArray());
final ExternalUser externalUser = idap.authenticate(credentials);

Error thrown -

javax.security.auth.login.LoginException: Unable to authenticate against LDAP server: INVALID_CREDENTIALS: Bind failed: Attempt to lookup non-existant entry: cn=steve+uid=steve+sn=jobs,dc=example,dc=com

Update: Identity provider config

# Configuration created by Apache Sling JCR Installer
userPool.maxActive=L"8"
searchTimeout="60s"
host.name="localhost"
customattributes=[""]
adminPool.maxActive=L"8"
group.makeDnPath=B"false"
user.baseDN="ou\=Users,dc\=example,dc\=com"
group.objectclass=["groupOfNames"]
user.objectclass=["person"]
userPool.lookupOnValidate=B"true"
host.noCertCheck=B"false"
user.makeDnPath=B"true"
bind.dn="uid\=admin,ou\=system"
group.baseDN="ou\=Groups,dc\=example,dc\=com"
group.extraFilter=""
user.extraFilter=""
host.port=I"10389"
bind.password="secret"
adminPool.lookupOnValidate=B"true"
useUidForExtId=B"false"
group.nameAttribute="cn"
provider.name="ldap"
host.ssl=B"false"
host.tls=B"false"
user.idAttribute="uid"
group.memberAttribute="member"

Sync Handler

# Configuration created by Apache Sling JCR Installer
group.pathPrefix=""
user.dynamicMembership=B"false"
group.expirationTime="1d"
user.membershipExpTime="1h"
user.pathPrefix=""
user.propertyMapping=["profile/nt:primaryType\=\"nt:unstructured\"","profile/givenName\=cn","profile/rep:password\=userPassword"]
handler.name="syncHandlerDefault"
enableRFC7613UsercaseMappedProfile=B"false"
user.autoMembership=[""]
user.expirationTime="1h"
group.propertyMapping=[""]
group.autoMembership=[""]
user.disableMissing=B"false"
user.membershipNestingDepth=I"3"

External login

# Configuration created by Apache Sling JCR Installer
jaas.controlFlag="SUFFICIENT"
jaas.ranking=I"50"
sync.handlerName="syncHandlerDefault"
jaas.realmName=""
idp.name="ldap"

LDIF file for users

version: 1

dn: ou=Users,dc=example,dc=com
objectClass: organizationalUnit
objectClass: top
ou: Users

dn: cn=eden+sn=hazard+uid=eden,ou=Users,dc=example,dc=com
objectClass: uidObject
objectClass: person
objectClass: top
cn: eden
sn: hazard
uid: eden
userPassword: {SSHA}O/t6ZRnWZTLhHla106Hp5nIWy85b0kgwNmeY3w==

dn: cn=rohit+sn=sharma+uid=rohit,ou=Users,dc=example,dc=com
objectClass: uidObject
objectClass: person
objectClass: top
cn: rohit
sn: sharma
uid: rohit
userPassword: {SSHA}9fzIkizxYg3LGG8n0jf/tnpv//qiNlxtS6mnWg==

dn: cn=harry+uid=harry+sn=kane,ou=Users,dc=example,dc=com
objectClass: uidObject
objectClass: person
objectClass: top
cn: harry
sn: kane
uid: harry
userPassword: {SSHA}WjNxB0ZDsmKfpjN0zwgsvDtZ4c/lHrIZXb7T2g==

dn: cn=cristiano+uid=cristiano+sn=ronaldo,ou=Users,dc=example,dc=com
objectClass: uidObject
objectClass: person
objectClass: top
cn: cristiano
sn: ronaldo
uid: cristiano
userPassword: {SSHA}ykzpMLVAbK99hfbCwwGgmgcDVzDV/Kfl0TlA8Q==

Solution

  • For LDAP Login you need 3 OSGi configs. The most difficult one, you already have.

    Here an example:

    org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModuleFactory-emea

    "jcr:primaryType": "sling:OsgiConfig",
    "jaas.ranking": "50",
    "jaas.controlFlag": "SUFFICIENT",
    "jaas.realmName": "",
    "idp.name": "ldap-emea",
    "sync.handlerName": "sync-emea"
    

    org.apache.jackrabbit.oak.security.authentication.ldap.impl.LdapIdentityProvider-emea

    "jcr:primaryType": "sling:OsgiConfig",
    "provider.name": "ldap-emea",
    "host.name": "ldap-emea.emea.mycompany.internal",
    "host.port": "3269",
    "host.ssl": true,
    "host.tls": true,
    "host.noCertCheck": false,
    "bind.dn": "CN=xxxx,OU=xxxx,OU=xxxx,OU=xxxx,DC=emea,DC=dir",
    "bind.password": "very secret",
    "searchTimeout": "60s",
    "adminPool.maxActive": "8",
    "adminPool.lookupOnValidate": true,
    "userPool.maxActive": "8",
    "userPool.lookupOnValidate": true,
    "user.baseDN": "DC=emea,DC=dir",
    "user.objectclass": "user",
    "user.idAttribute": "sAMAccountName",
    "user.extraFilter": "xxx very specific LDAP query xxxxx",
    "user.makeDnPath": false,
    "group.baseDN": "OU=Groups,OU=Common,DC=emea,DC=dir",
    "group.objectclass": "group",
    "group.nameAttribute": "cn",
    "group.extraFilter": "xxx very specific LDAP query xxxxx",
    "group.makeDnPath": false,
    "group.memberAttribute": "member",
    "customattributes": []
    

    org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncHandler-emea

    "jcr:primaryType": "sling:OsgiConfig",
    "handler.name": "sync-emea",
    "user.expirationTime": "1h",
    "user.autoMembership": [],
    "user.propertyMapping": [
       "rep:fullname=cn",
       "profile/email=mail",
       "profile/familyName=sn",
       "profile/givenName=givenName",
       "profile/aboutMe=description",
       "profile/country=co",
       "profile/jobTitle=department",
       "profile/phoneNumber=telephoneNumber",
       "profile/mobile=mobile",
       "profile/postalCode=postalCode",
       "profile/street=streetAddress",
       "preferences/language=\"en\""
    ],
    "user.pathPrefix": "my-company/emea",
    "user.membershipExpTime": "1h",
    "user.membershipNestingDepth": "3",
    "group.expirationTime": "1d",
    "group.autoMembership": [],
    "group.propertyMapping": [
       "profile/givenName=name",
       "profile/aboutMe=description"
    ],
    "group.pathPrefix": "my-company/nested/emea",
    "user.dynamicMembership": false,
    "user.disableMissing": false,
    "enableRFC7613UsercaseMappedProfile": false
    

    kind regards, Alex


    I additionally setup an Apache Directory Server and filled it with the sample data (Sailors of the seven seas) http://directory.apache.org/apacheds/basic-ug/1.5-sample-configuration.html

    The following configuration worked for me (synced users and groups via JMX, successful login of a user, including auto sync):

    http://localhost:4502/apps/ldap-test.9.json

      {
      "jcr:primaryType": "nt:folder",
      "config": {
        "jcr:primaryType": "sling:Folder",
        "org.apache.jackrabbit.oak.security.authentication.ldap.impl.LdapIdentityProvider-test": {
          "jcr:primaryType": "sling:OsgiConfig",
          "provider.name": "ldap-test-alex",
          "host.name": "localhost",
          "host.port": "10389",
          "host.ssl": false,
          "host.tls": false,
          "bind.dn": "uid=admin,ou=system",
          "bind.password": "secret",
          "user.objectclass": "person",
          "user.baseDN": "ou=people,o=sevenSeas",
          "user.idAttribute": "uid",
          "group.objectclass": "groupOfUniqueNames",
          "group.baseDN": "ou=groups,o=sevenSeas",
          "group.nameAttribute": "cn",
          "group.memberAttribute": "uniquemember",
        },
        "org.apache.jackrabbit.oak.spi.security.authentication.external.impl.DefaultSyncHandler-test": {
          "jcr:primaryType": "sling:OsgiConfig",
          "handler.name": "ldap-sync-test-alex",
          "user.pathPrefix": "ldap-test",
          "group.pathPrefix": "ldap-test",
          "user.membershipNestingDepth": 1,
          "user.autoMembership": [
            "contributor"
          ],
          "user.propertyMapping": [
            "profile/email=mail",
            "profile/familyName=sn",
            "profile/givenName=givenName",
            "profile/aboutMe=description"
          ]
        },
        "org.apache.jackrabbit.oak.spi.security.authentication.external.impl.ExternalLoginModuleFactory-test": {
          "jcr:primaryType": "sling:OsgiConfig",
          "idp.name": "ldap-test-alex",
          "sync.handlerName": "ldap-sync-test-alex",
          "jaas.controlFlag": "SUFFICIENT",
          "jaas.ranking": "50"
        }
      }
    }
    

    Check, to have the following

    Alex