Working with LDAP Authentication

1. Understanding LDAP Protocol

AspectDetail
SpecRFC 4511 (LDAPv3)
Ports389 (ldap), 636 (ldaps), 3268/3269 (AD GC)
Data modelDIT (Directory Information Tree) of entries with DN
SchemaobjectClass + attributes (inetOrgPerson, person, user)

2. Implementing LDAP Bind

Bind TypeUse
SimpleDN + password (clear → require TLS)
SASLGSSAPI / DIGEST-MD5 / EXTERNAL (mTLS)
AnonymousLookup-only (often disabled)

3. Using Simple Bind

Example: Spring LDAP authentication

// Two-step: search by username, then bind with DN+password
DirContextOperations ctx = ldapTemplate.searchForContext(
  LdapQueryBuilder.query().where("uid").is(username));
String userDn = ctx.getNameInNamespace();
new LdapTemplate(new LdapContextSource() {{
  setUrl("ldaps://ldap.example.com:636");
  setUserDn(userDn);
  setPassword(password);
}}).lookup("");  // throws on bad credentials

4. Implementing SASL Authentication

MechanismNotes
GSSAPIKerberos-based, SSO
EXTERNALUses TLS client cert identity
DIGEST-MD5 DEPRECATEDWeak hash
SCRAM-SHA-256Modern challenge–response

5. Querying LDAP Directory

FilterExample
Equality(uid=alice)
Substring(cn=Al*)
AND(&(objectClass=user)(department=eng))
OR(|(uid=a)(uid=b))
Member check (AD)(memberOf=CN=Admins,...)
Nested (AD)memberOf:1.2.840.113556.1.4.1941:
Warning: Always escape user input in LDAP filters — LDAP injection allows auth bypass via crafted *, (, ), \.

6. Using LDAP with Active Directory

AD AttributeUse
sAMAccountNamePre-Windows 2000 logon name
userPrincipalNameemail-style (user@domain.com)
objectGUIDImmutable identifier
memberOfGroup memberships (non-transitive)
userAccountControlBit flags (disabled, locked, etc.)
Global CatalogPort 3268, forest-wide subset

7. Implementing LDAP Connection Pooling

SettingDetail
Pool size10–50 connections per node
Max idle5 min
ValidationPeriodic RootDSE read
FailoverMultiple LDAP URIs, retry on error
LibraryUnboundID LDAP SDK, ldapjs (Node), python-ldap

8. Validating LDAP Certificates

ConcernMitigation
MitMAlways use ldaps:// or StartTLS
Trust storePin internal CA cert
HostnameVerify SAN matches LDAP URI
Channel bindingRequired for modern AD (LDAP signing/sealing)

9. Implementing LDAP Group Membership

Example: Resolve groups

String filter = "(&(objectClass=user)(sAMAccountName={0}))";
DirContextOperations user = template.searchForContext(
  query().base("OU=Users,DC=example,DC=com")
         .searchScope(SUBTREE)
         .filter(filter, username));
String[] groups = user.getStringAttributes("memberOf"); // distinguished names

10. Handling LDAP Authentication Errors

Result CodeMeaning
49 (invalidCredentials)Bad password or unknown user
49 + 533Account disabled (AD subcode)
49 + 532Password expired (AD)
49 + 775Account locked (AD)
50insufficientAccessRights
51busy — retry with backoff
53unwillingToPerform (e.g., password complexity)