Skip to content

Commit 2cccf22

Browse files
bbertorwinch
authored andcommitted
Add Flag to enable searching of LDAP groups on subtrees
Closes gh-8939
1 parent 64a5bb0 commit 2cccf22

File tree

3 files changed

+66
-1
lines changed

3 files changed

+66
-1
lines changed

config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderBuilderSecurityBuilderTests.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
import java.io.IOException;
4343
import java.net.ServerSocket;
4444
import java.util.List;
45-
45+
import javax.naming.directory.SearchControls;
4646
import static java.util.Collections.singleton;
4747
import static org.assertj.core.api.Assertions.assertThat;
4848
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
@@ -67,6 +67,8 @@ public void defaultConfiguration() {
6767
assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupRoleAttribute", "cn");
6868
assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupSearchBase", "");
6969
assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupSearchFilter", "(uniqueMember={0})");
70+
assertThat(authoritiesPopulator).extracting("searchControls").hasFieldOrPropertyWithValue("searchScope",
71+
SearchControls.ONELEVEL_SCOPE);
7072
assertThat(ReflectionTestUtils.getField(getAuthoritiesMapper(provider), "prefix")).isEqualTo("ROLE_");
7173
}
7274

@@ -124,6 +126,29 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
124126
// @formatter:on
125127
}
126128

129+
@Test
130+
public void groupSubtreeSearchCustom() {
131+
this.spring.register(GroupSubtreeSearchConfig.class).autowire();
132+
LdapAuthenticationProvider provider = ldapProvider();
133+
134+
assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "searchControls"))
135+
.extracting("searchScope").isEqualTo(SearchControls.SUBTREE_SCOPE);
136+
}
137+
138+
@EnableWebSecurity
139+
static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig {
140+
// @formatter:off
141+
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
142+
auth
143+
.ldapAuthentication()
144+
.contextSource(contextSource())
145+
.userDnPatterns("uid={0},ou=people")
146+
.groupSearchFilter("ou=groupName")
147+
.groupSearchSubtree(true);
148+
}
149+
// @formatter:on
150+
}
151+
127152
@Test
128153
public void rolePrefixCustom() {
129154
this.spring.register(RolePrefixConfig.class).autowire();

config/src/integration-test/java/org/springframework/security/config/annotation/authentication/ldap/LdapAuthenticationProviderConfigurerTests.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121

2222
import org.springframework.beans.factory.annotation.Autowired;
2323
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
24+
import org.springframework.security.config.annotation.authentication.ldap.LdapAuthenticationProviderBuilderSecurityBuilderTests.BaseLdapProviderConfig;
2425
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
2526
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
2627
import org.springframework.security.config.test.SpringTestRule;
28+
import org.springframework.security.core.authority.AuthorityUtils;
2729
import org.springframework.security.core.authority.SimpleGrantedAuthority;
2830
import org.springframework.test.web.servlet.MockMvc;
2931

@@ -70,6 +72,15 @@ public void authenticationManagerWhenPortZeroThenAuthenticates() throws Exceptio
7072
.andExpect(authenticated().withUsername("bob"));
7173
}
7274

75+
@Test
76+
public void authenticationManagerWhenSearchSubtreeThenNestedGroupFound() throws Exception {
77+
this.spring.register(GroupSubtreeSearchConfig.class).autowire();
78+
79+
this.mockMvc.perform(formLogin().user("ben").password("benspassword"))
80+
.andExpect(authenticated().withUsername("ben").withAuthorities(
81+
AuthorityUtils.createAuthorityList("ROLE_SUBMANAGERS", "ROLE_MANAGERS", "ROLE_DEVELOPERS")));
82+
}
83+
7384
@EnableWebSecurity
7485
static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
7586
// @formatter:off
@@ -121,4 +132,18 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
121132
.port(0);
122133
}
123134
}
135+
136+
@EnableWebSecurity
137+
static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig {
138+
// @formatter:off
139+
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
140+
auth
141+
.ldapAuthentication()
142+
.groupSearchBase("ou=groups")
143+
.groupSearchFilter("(member={0})")
144+
.groupSearchSubtree(true)
145+
.userDnPatterns("uid={0},ou=people");
146+
}
147+
// @formatter:on
148+
}
124149
}

config/src/main/java/org/springframework/security/config/annotation/authentication/configurers/ldap/LdapAuthenticationProviderConfigurer.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
6161
extends SecurityConfigurerAdapter<AuthenticationManager, B> {
6262
private String groupRoleAttribute = "cn";
6363
private String groupSearchBase = "";
64+
private boolean groupSearchSubtree = false;
6465
private String groupSearchFilter = "(uniqueMember={0})";
6566
private String rolePrefix = "ROLE_";
6667
private String userSearchBase = ""; // only for search
@@ -130,6 +131,7 @@ private LdapAuthoritiesPopulator getLdapAuthoritiesPopulator() {
130131
contextSource, groupSearchBase);
131132
defaultAuthoritiesPopulator.setGroupRoleAttribute(groupRoleAttribute);
132133
defaultAuthoritiesPopulator.setGroupSearchFilter(groupSearchFilter);
134+
defaultAuthoritiesPopulator.setSearchSubtree(groupSearchSubtree);
133135
defaultAuthoritiesPopulator.setRolePrefix(this.rolePrefix);
134136

135137
this.ldapAuthoritiesPopulator = defaultAuthoritiesPopulator;
@@ -320,6 +322,19 @@ public LdapAuthenticationProviderConfigurer<B> groupSearchBase(String groupSearc
320322
return this;
321323
}
322324

325+
/**
326+
* If set to true, a subtree scope search will be performed for group membership. If false a
327+
* single-level search is used.
328+
*
329+
* @param searchSubtree set to true to enable searching of the entire tree below the
330+
* <tt>groupSearchBase</tt>.
331+
* @return the {@link LdapAuthenticationProviderConfigurer} for further customizations
332+
*/
333+
public LdapAuthenticationProviderConfigurer<B> groupSearchSubtree(boolean groupSearchSubtree) {
334+
this.groupSearchSubtree = groupSearchSubtree;
335+
return this;
336+
}
337+
323338
/**
324339
* The LDAP filter to search for groups. Defaults to "(uniqueMember={0})". The
325340
* substituted parameter is the DN of the user.

0 commit comments

Comments
 (0)