This question is about how to use multiple group search bases instead of the one.
I used an example provided by samaddico (simple spring security + LDAP example), modified it for single group search base with provided server / user / LDAP configuration text. It uses a service account to connect to ldap and a user which then tries to authenticate for certain simple web pages. This approach works but lacks ability to collect membership / roles from different groups in the search tree.
Spring Security provides classes LdapContextSource
and MultipleLdapAuthoritiesPopulator
to allow for searching for roles in different locations.
Now here is the code which will result in the error shown below:
LDAP Configuration:
* Create an implementation of org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator which can call
multiple instances of LdapAuthoritiesPopulator.
* Then create one LdapAuthoritiesPopulatorfor each 'groupSearchBase' that I wanted to query.
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
LdapContextSource contextSource = contextSource();
MultipleLdapAuthoritiesPopulator multipleLdapAuthoritiesPopulator = new MultipleLdapAuthoritiesPopulator(
new DefaultLdapAuthoritiesPopulator(contextSource, ldapGroupSearchBaseA),
new DefaultLdapAuthoritiesPopulator(contextSource, ldapGroupSearchBaseB),
new DefaultLdapAuthoritiesPopulator(contextSource, ldapGroupSearchBaseC));
auth
.ldapAuthentication()
.contextSource(contextSource)
.ldapAuthoritiesPopulator(multipleLdapAuthoritiesPopulator)
.userSearchFilter(ldapUserSearchFilter)
.userSearchBase(ldapUserSearchBase);
}
class MultipleLdapAuthoritiesPopulator implements LdapAuthoritiesPopulator {
private List<LdapAuthoritiesPopulator> authoritiesPopulators;
public MultipleLdapAuthoritiesPopulator(LdapAuthoritiesPopulator...authoritiesPopulators) {
this.authoritiesPopulators = Arrays.asList(authoritiesPopulators);
}
@Override
public Collection<? extends GrantedAuthority> getGrantedAuthorities(DirContextOperations userData, String username) {
List<GrantedAuthority> grantedAuthorities = authoritiesPopulators.stream()
.map(authPopulator -> authPopulator.getGrantedAuthorities(userData, username))
.flatMap(Collection::stream)
.collect(Collectors.toList());
return grantedAuthorities;
}
}
/**
* Creates context source object instead of configuring it with AuthenticationBuilder
* @return Context source object used for accessing ldap server
*/
@Bean
public LdapContextSource contextSource() {
LdapContextSource contextSource= new LdapContextSource();
contextSource.setUrl(ldapUrl);
contextSource.setUserDn(ldapManagerDn);
contextSource.setPassword(ldapManagerPassword);
contextSource.afterPropertiesSet();
return contextSource;
}
Session Configuration:
/**
* This is essential to make sure that the Spring Security session registry is notified when the session is destroyed.
* @return
*/
@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
return new HttpSessionEventPublisher();
}
The Spring Application tells me that my service account got successful connected to LDAP server.
DEBUG 17220 --- [nio-8080-exec-5] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@c1e15be1: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@380f4: RemoteIpAddress: 127.0.0.1; SessionId: 0A82CE8FA4FB9EB248D756EEE8134CAE; Granted Authorities: ROLE_ANONYMOUS
The error then is thrown when the found user is beeing tried to bind:
DEBUG 17220 --- [nio-8080-exec-8] o.s.s.l.a.BindAuthenticator : Failed to bind as CN=familyName\, name,OU=Group: org.springframework.ldap.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090453, comment: AcceptSecurityContext error, data 52e, v3839 ]; nested exception is javax.naming.AuthenticationException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C090453, comment: AcceptSecurityContext error, data 52e, v3839 ]
DEBUG 17220 --- [nio-8080-exec-8] w.a.UsernamePasswordAuthenticationFilter : Authentication request failed: org.springframework.security.authentication.BadCredentialsException: Bad credentials
To sum this up: my credentials are correct for a single group base without using LdapContextSource
and MultipleLdapAuthoritiesPopulator
. But the authentication process seems not to provide the enteret password for my user with multiple group bases.