Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
import java.io.IOException;
import java.net.ServerSocket;
import java.util.List;

import javax.naming.directory.SearchControls;
import static java.util.Collections.singleton;
import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestBuilders.formLogin;
Expand All @@ -67,6 +67,8 @@ public void defaultConfiguration() {
assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupRoleAttribute", "cn");
assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupSearchBase", "");
assertThat(authoritiesPopulator).hasFieldOrPropertyWithValue("groupSearchFilter", "(uniqueMember={0})");
assertThat(authoritiesPopulator).extracting("searchControls").hasFieldOrPropertyWithValue("searchScope",
SearchControls.ONELEVEL_SCOPE);
assertThat(ReflectionTestUtils.getField(getAuthoritiesMapper(provider), "prefix")).isEqualTo("ROLE_");
}

Expand Down Expand Up @@ -124,6 +126,29 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// @formatter:on
}

@Test
public void groupSubtreeSearchCustom() {
this.spring.register(GroupSubtreeSearchConfig.class).autowire();
LdapAuthenticationProvider provider = ldapProvider();

assertThat(ReflectionTestUtils.getField(getAuthoritiesPopulator(provider), "searchControls"))
.extracting("searchScope").isEqualTo(SearchControls.SUBTREE_SCOPE);
}

@EnableWebSecurity
static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig {
// @formatter:off
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.contextSource(contextSource())
.userDnPatterns("uid={0},ou=people")
.groupSearchFilter("ou=groupName")
.groupSearchSubtree(true);
}
// @formatter:on
}

@Test
public void rolePrefixCustom() {
this.spring.register(RolePrefixConfig.class).autowire();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.ldap.LdapAuthenticationProviderBuilderSecurityBuilderTests.BaseLdapProviderConfig;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.test.SpringTestRule;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.test.web.servlet.MockMvc;

Expand Down Expand Up @@ -70,6 +72,15 @@ public void authenticationManagerWhenPortZeroThenAuthenticates() throws Exceptio
.andExpect(authenticated().withUsername("bob"));
}

@Test
public void authenticationManagerWhenSearchSubtreeThenNestedGroupFound() throws Exception {
this.spring.register(GroupSubtreeSearchConfig.class).autowire();

this.mockMvc.perform(formLogin().user("ben").password("benspassword"))
.andExpect(authenticated().withUsername("ben").withAuthorities(
AuthorityUtils.createAuthorityList("ROLE_SUBMANAGERS", "ROLE_MANAGERS", "ROLE_DEVELOPERS")));
}

@EnableWebSecurity
static class MultiLdapAuthenticationProvidersConfig extends WebSecurityConfigurerAdapter {
// @formatter:off
Expand Down Expand Up @@ -121,4 +132,18 @@ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
.port(0);
}
}

@EnableWebSecurity
static class GroupSubtreeSearchConfig extends BaseLdapProviderConfig {
// @formatter:off
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.ldapAuthentication()
.groupSearchBase("ou=groups")
.groupSearchFilter("(member={0})")
.groupSearchSubtree(true)
.userDnPatterns("uid={0},ou=people");
}
// @formatter:on
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ public class LdapAuthenticationProviderConfigurer<B extends ProviderManagerBuild
extends SecurityConfigurerAdapter<AuthenticationManager, B> {
private String groupRoleAttribute = "cn";
private String groupSearchBase = "";
private boolean groupSearchSubtree = false;
private String groupSearchFilter = "(uniqueMember={0})";
private String rolePrefix = "ROLE_";
private String userSearchBase = ""; // only for search
Expand Down Expand Up @@ -130,6 +131,7 @@ private LdapAuthoritiesPopulator getLdapAuthoritiesPopulator() {
contextSource, groupSearchBase);
defaultAuthoritiesPopulator.setGroupRoleAttribute(groupRoleAttribute);
defaultAuthoritiesPopulator.setGroupSearchFilter(groupSearchFilter);
defaultAuthoritiesPopulator.setSearchSubtree(groupSearchSubtree);
defaultAuthoritiesPopulator.setRolePrefix(this.rolePrefix);

this.ldapAuthoritiesPopulator = defaultAuthoritiesPopulator;
Expand Down Expand Up @@ -320,6 +322,19 @@ public LdapAuthenticationProviderConfigurer<B> groupSearchBase(String groupSearc
return this;
}

/**
* If set to true, a subtree scope search will be performed for group membership. If false a
* single-level search is used.
*
* @param searchSubtree set to true to enable searching of the entire tree below the
* <tt>groupSearchBase</tt>.
* @return the {@link LdapAuthenticationProviderConfigurer} for further customizations
*/
public LdapAuthenticationProviderConfigurer<B> groupSearchSubtree(boolean groupSearchSubtree) {
this.groupSearchSubtree = groupSearchSubtree;
return this;
}

/**
* The LDAP filter to search for groups. Defaults to "(uniqueMember={0})". The
* substituted parameter is the DN of the user.
Expand Down