diff --git a/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java b/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java index 43bb8305279..9982bd88dfb 100644 --- a/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java +++ b/ldap/src/main/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProvider.java @@ -94,6 +94,8 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda private final String domain; private final String rootDn; + private final String searchRoot; + private final String searchFilter; private final String url; private boolean convertSubErrorCodesToExceptions; @@ -112,11 +114,23 @@ public final class ActiveDirectoryLdapAuthenticationProvider extends AbstractLda * @param url an LDAP url (or multiple URLs) */ public ActiveDirectoryLdapAuthenticationProvider(String domain, String url) { + this(domain, url, null, null); + } + + /** + * @param domain the domain name (may be null or empty) + * @param url an LDAP url (or multiple URLs) + * @param searchRoot the LDAP search root (may be null or empty) + * @param searchFilter The LDAP search filter used to restrict results (may be null or empty) + */ + public ActiveDirectoryLdapAuthenticationProvider(String domain, String url, String searchRoot, String searchFilter) { Assert.isTrue(StringUtils.hasText(url), "Url cannot be empty"); this.domain = StringUtils.hasText(domain) ? domain.toLowerCase() : null; //this.url = StringUtils.hasText(url) ? url : null; this.url = url; rootDn = this.domain == null ? null : rootDnFromDomain(this.domain); + this.searchRoot = StringUtils.hasText(searchRoot) ? searchRoot : null; + this.searchFilter = StringUtils.hasText(searchFilter) ? searchFilter : "(&(objectClass=user)(userPrincipalName={0}))"; } @Override @@ -275,11 +289,9 @@ private DirContextOperations searchForUser(DirContext ctx, String username) thro SearchControls searchCtls = new SearchControls(); searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE); - String searchFilter = "(&(objectClass=user)(userPrincipalName={0}))"; - final String bindPrincipal = createBindPrincipal(username); - String searchRoot = rootDn != null ? rootDn : searchRootFromPrincipal(bindPrincipal); + final String searchRoot = StringUtils.hasText(this.searchRoot) ? this.searchRoot : (rootDn != null ? rootDn : searchRootFromPrincipal(bindPrincipal)); try { return SpringSecurityLdapTemplate.searchForSingleEntryInternal(ctx, searchCtls, searchRoot, searchFilter, diff --git a/ldap/src/test/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProviderTests.java b/ldap/src/test/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProviderTests.java index d3c31378144..e3258310aa0 100644 --- a/ldap/src/test/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProviderTests.java +++ b/ldap/src/test/java/org/springframework/security/ldap/authentication/ad/ActiveDirectoryLdapAuthenticationProviderTests.java @@ -97,6 +97,32 @@ public void successfulAuthenticationProducesExpectedAuthorities() throws Excepti assertEquals(1, result.getAuthorities().size()); } + @Test + public void successfulAuthenticationProducesExpectedAuthoritiesWithCustomSearchRootAndFilter() throws Exception { + provider = new ActiveDirectoryLdapAuthenticationProvider("mydomain.eu", "ldap://192.168.1.200/", "OU=people,DC=example,DC=com", "(&(objectClass=user)(OU=groups,OU=people,DC=example,DC=com))"); + + DirContext ctx = mock(DirContext.class); + when(ctx.getNameInNamespace()).thenReturn(""); + + DirContextAdapter dca = new DirContextAdapter(); + SearchResult sr = new SearchResult("CN=Joe Jannsen,CN=Users", dca, dca.getAttributes()); + when(ctx.search(any(Name.class), any(String.class), any(Object[].class), any(SearchControls.class))) + .thenReturn(new MockNamingEnumeration(sr)) + .thenReturn(new MockNamingEnumeration(sr)); + + provider.contextFactory = createContextFactoryReturning(ctx); + + Authentication result = provider.authenticate(joe); + + assertEquals(0, result.getAuthorities().size()); + + dca.addAttributeValue("memberOf","CN=Admin,CN=Users,DC=mydomain,DC=eu"); + + result = provider.authenticate(joe); + + assertEquals(1, result.getAuthorities().size()); + } + @Test public void nullDomainIsSupportedIfAuthenticatingWithFullUserPrincipal() throws Exception { provider = new ActiveDirectoryLdapAuthenticationProvider(null, "ldap://192.168.1.200/");