How to Configure Apache LDAP Authentication for Nested Active Directory Groups


2 views

When implementing LDAP authentication with Apache, many administrators encounter limitations with nested Active Directory group memberships. The standard configuration using Require ldap-group only checks direct group membership, ignoring the hierarchical structure common in enterprise environments.

Your existing setup looks like this:

AuthName            "whatever"
AuthType            Basic
AuthBasicProvider   ldap
AuthLDAPUrl         "ldap://server/OU=SBSUsers,OU=Users,OU=MyBusiness,DC=company,DC=local?sAMAccountName?sub?(objectClass=*)"
Require ldap-group  CN=MySpecificGroup,OU=Security Groups,OU=MyBusiness,DC=company,DC=local

The mod_authnz_ldap module doesn't automatically resolve nested group memberships due to:

  • Performance considerations (recursive queries can be expensive)
  • Potential circular reference risks
  • Varying implementations across directory servers

For Windows Server 2003 and later, we can leverage the matching rule extension:

Require ldap-attribute memberOf:1.2.840.113556.1.4.1941:=CN=MySpecificGroup,OU=Security Groups,OU=MyBusiness,DC=company,DC=local

Here's a full working configuration that handles nested groups:

<Location /secure>
    AuthType Basic
    AuthName "Restricted Area"
    AuthBasicProvider ldap
    AuthLDAPUrl "ldap://dc.company.local:389/DC=company,DC=local?sAMAccountName?sub?(objectClass=user)"
    AuthLDAPBindDN "CN=LDAP Bind,OU=Service Accounts,DC=company,DC=local"
    AuthLDAPBindPassword "password"
    AuthLDAPGroupAttribute member
    AuthLDAPGroupAttributeIsDN on
    AuthLDAPMaxSubGroupDepth 10
    Require ldap-attribute memberOf:1.2.840.113556.1.4.1941:=CN=MySpecificGroup,OU=Security Groups,OU=MyBusiness,DC=company,DC=local
</Location>
Parameter Purpose
AuthLDAPMaxSubGroupDepth Controls recursion depth (default 10)
memberOf:1.2.840.113556.1.4.1941 LDAP_MATCHING_RULE_IN_CHAIN OID
AuthLDAPGroupAttributeIsDN Required for proper group resolution

If the previous method doesn't work, you can implement a custom solution:

AuthLDAPSubGroupClass group
AuthLDAPSubGroupAttribute member
Require ldap-filter "(&(objectClass=user)(memberOf:1.2.840.113556.1.4.1941:=CN=MySpecificGroup,OU=Security Groups,OU=MyBusiness,DC=company,DC=local))"

When working with nested groups:

  • Limit the maximum recursion depth
  • Consider using global catalog servers
  • Implement caching where possible
  • Monitor LDAP query response times

Use ldapsearch to verify group membership resolution:

ldapsearch -H ldap://dc.company.local -x -D "binduser@company.local" -W -b "DC=company,DC=local" \
"(memberOf:1.2.840.113556.1.4.1941:=CN=MySpecificGroup,OU=Security Groups,OU=MyBusiness,DC=company,DC=local)" \
sAMAccountName

When configuring LDAP authentication in Apache, you might encounter a common limitation: the default setup doesn't automatically recognize users in nested groups. Consider this typical configuration:

AuthName            "whatever"
AuthType            Basic
AuthBasicProvider   ldap
AuthLDAPUrl         "ldap://server/OU=SBSUsers,OU=Users,OU=MyBusiness,DC=company,DC=local?sAMAccountName?sub?(objectClass=*)"
Require ldap-group  CN=MySpecificGroup,OU=Security Groups,OU=MyBusiness,DC=company,DC=local

This works fine for users directly in MySpecificGroup, but fails for users in nested groups like MyOtherGroup.

Apache's mod_authnz_ldap doesn't automatically expand group membership by default. This is primarily due to:

  • Performance considerations (recursive group expansion can be expensive)
  • Potential for infinite recursion in circular group references
  • Security implications of deep group nesting

To enable nested group support, you need to modify your configuration:

AuthLDAPGroupAttribute member
AuthLDAPGroupAttributeIsDN on
AuthLDAPSubGroupClass group
AuthLDAPSubGroupAttribute member

Here's a complete working example:

<Location /secure>
    AuthName "Restricted Area"
    AuthType Basic
    AuthBasicProvider ldap
    AuthLDAPUrl "ldap://dc.company.local/OU=Users,DC=company,DC=local?sAMAccountName?sub?(objectClass=user)"
    AuthLDAPBindDN "CN=ServiceAccount,OU=Service Accounts,DC=company,DC=local"
    AuthLDAPBindPassword "password"
    
    # Nested group configuration
    AuthLDAPGroupAttribute member
    AuthLDAPGroupAttributeIsDN on
    AuthLDAPSubGroupClass group
    AuthLDAPSubGroupAttribute member
    
    Require ldap-group CN=MySpecificGroup,OU=Groups,DC=company,DC=local
</Location>

For more complex scenarios, you can use LDAP filters instead of group membership checks:

Require ldap-filter memberOf:1.2.840.113556.1.4.1941:=CN=MySpecificGroup,OU=Groups,DC=company,DC=local

The 1.2.840.113556.1.4.1941 OID enables recursive group expansion in the LDAP query itself.

When working with nested groups:

  • Limit the depth of group nesting (3-4 levels max)
  • Consider caching authentication results
  • Use specific OUs rather than broad searches
  • Monitor LDAP server performance

If nested groups still don't work:

  1. Verify your service account has permissions to read group membership
  2. Check for circular group references
  3. Test with a direct LDAP query first
  4. Enable debug logging with LogLevel debug