I've configured the Spring Boot Security as per: https://spring.io/guides/gs/securing-web/
I am able to login using my credentials perfectly. However, I need to add a checking that the AD user must also belong to a specific AD group (ie. AD-this-is-a-specific-group ). On login, if the user does not belong to the specific AD group, then it should return a login error.
I've been searching for hours now and cannot seem to find a clear way to do this in the WebSecurityConfigurerAdapter
, am I using the auth.groupSearchFilter
correctly?
Here is my code:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
Environment env;
public LdapContextSource contextSource () {
LdapContextSource contextSource= new LdapContextSource();
contextSource.setUrl(env.getRequiredProperty("ldap.url"));
contextSource.setBase(env.getRequiredProperty("ldap.baseDn"));
contextSource.setUserDn(env.getRequiredProperty("ldap.bindDn"));
contextSource.setPassword(env.getRequiredProperty("ldap.batchPassword"));
contextSource.afterPropertiesSet();
return contextSource;
}
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception {
auth.ldapAuthentication()
.userSearchFilter("(cn={0})")
.groupSearchBase("OU=Account Groups,OU=ITS Security")
.groupSearchFilter("(cn=AD-this-is-a-specific-group)")
.contextSource(contextSource());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().fullyAuthenticated()
.and()
.formLogin();
}
Not sure if this is the best way to do this ( in terms of Spring Security's lifecycle ), but basically I provided my own DefaultLdapAuthoritiesPopulator
, where I only override the getGroupMembershipRoles
.
First thing though, I have wrong auth.groupSearchFilter
above, it should be:
.groupSearchFilter("(member={0})")
Second, I've created an anonymous class with overridden method (that calls the super and checks for a the membership in the list of roles):
auth
.ldapAuthentication()
.ldapAuthoritiesPopulator(new DefaultLdapAuthoritiesPopulator(contextSource, "OU=Account Groups,OU=ITS Security") {
@Override
public Set<GrantedAuthority> getGroupMembershipRoles(String userDn, String username) {
Set<GrantedAuthority> groupMembershipRoles = super.getGroupMembershipRoles(userDn, username);
boolean isMemberOfSpecificAdGroup = false;
for (GrantedAuthority grantedAuthority : groupMembershipRoles) {
if ("ROLE_AD-this-is-a-specific-group".equals(grantedAuthority.toString())) {
isMemberOfSpecificAdGroup = true;
break;
}
}
if (!isMemberOfSpecificAdGroup ) {
throw new BadCredentialsException("User must be a member of " + "AD-this-is-a-specific-group");
}
return groupMembershipRoles;
}
})
.userSearchFilter("(cn={0})")
.groupSearchBase("OU=Account Groups,OU=ITS Security")
.groupSearchFilter("(member={0})")
.contextSource(contextSource);
I am sorry for beeing 5 years late for the party but I had the exact same problem with my very simple LDAP authentication implemented in Spring Boot.
I only wanted this: - Is it the correct username? - Is it the correct password? - If yes, is the usr in group MYGROUP?
So my configure method now looks really small. I added the populator in a separate bean, just realize that I needed to add it in "auth.ldapAuthentication" so it would be called.
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.userSearchFilter("uid={0}")
.ldapAuthoritiesPopulator(ldapAuthoritiesPopulator())
.groupSearchFilter("(member={0})")
.contextSource(contextSource());
}
@Bean
public LdapAuthoritiesPopulator ldapAuthoritiesPopulator() {
DefaultLdapAuthoritiesPopulator populi = new DefaultLdapAuthoritiesPopulator(contextSource(), "") {
@Override
public Set<GrantedAuthority> getGroupMembershipRoles(String userDn, String username) {
Set<GrantedAuthority> groupMembershipRoles = super.getGroupMembershipRoles(userDn, username);
boolean isMemberOfSpecificAdGroup = false;
for (GrantedAuthority grantedAuthority : groupMembershipRoles) {
if ("ROLE_MYGROUP".equals(grantedAuthority.toString())) {
isMemberOfSpecificAdGroup = true;
break;
}
}
if (!isMemberOfSpecificAdGroup) {
throw new BadCredentialsException("User must be a member of " + "ROLE_MYGROUP");
}
return groupMembershipRoles;
}
};
return populi;
}
@Bean
public DefaultSpringSecurityContextSource contextSource() {
return new DefaultSpringSecurityContextSource("ldap://blabla-some-url:389/dc=something,dc=something,dc=ch");
}
And by the way: The url did not work like mentioned in the Spring Boot guide it only worked like this, like everything in one line:
return new DefaultSpringSecurityContextSource("ldap://blabla-some-url:389/dc=something,dc=something,dc=ch");
And by the way for everyone following that guide: If you connect to an already existing LDAP server you don't need all those "spring.ldap.embedded" application properties.
So thank you alot for your help!
I'll put this here since I think it's the easier way without overriding any method.
In user search filter (i'll use yours) add the following if it corresponds to your LDAP structure
Original:
.userSearchFilter("(cn={0})")
Modified to search roles:
.userSearchFilter("(&(cn={0})(memberOf=CN=MYGROUP,OU=GROUP,DC=com,DC=company)")
This searches both the user and the membership
In my case I had to do this because I have 3 possible roles:
(&(cn={0})(|(group1)(group2)(group3)))
As you can see it searches user AND 1 OR more roles
Credit to this question's answer: Spring Security Ldap, log in only users in specified group
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.