I have implemented Active Directory Authentication using Spring Security and it's working fine. Now i want to get details of other users using their sAMAccountName. This Functionality I need for Admin to approve or reject user in our application. Using below code I'm able to fetch logged in user details.
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();
How to use this Authentication object to fetch other user details.
I'm using spring-security-ldap-4.0.1 spring-security-core-4.0.1
You should have a look at the UserDetailsContextMapper. There are already implementing classes that automatically map some attributes of a LDAP objects like InetOrgPersonContextMapper or PersonContextMapper. If there is any special attribute you'll have to enroll your own, e.g. we have reporting lines stored in AD using attributes of manager and directReports which I had to map manually.
public class CustomUserDetailsContextMapper extends LdapUserDetailsMapper implements UserDetailsContextMapper {
#Autowired
private LdapUserService ldapUserService;
#Override
public UserDetails mapUserFromContext(DirContextOperations ops, String username,
Collection<? extends GrantedAuthority> authorities) {
UserDetails details = super.mapUserFromContext(ops, username, authorities);
String manager = ops.getStringAttribute("manager");
String[] directReports = ops.getStringAttributes("directReports");
User user = new User(
username,
"",
details.isEnabled(),
details.isAccountNonExpired(),
details.isCredentialsNonExpired(),
details.isAccountNonLocked(),
details.getAuthorities(),
manager,
directReports);
return user;
}
#Override
public void mapUserToContext(UserDetails user, DirContextAdapter dir) {
super.mapUserToContext(user, dir);
}
}
And obviously you'll also have to tweak your UserDetails as well:
public class User extends org.springframework.security.core.userdetails.User {
private String manager;
private String[] directReports;
public User(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<? extends GrantedAuthority> authorities) {
super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
}
public User(String username, String password, boolean enabled, boolean accountNonExpired,
boolean credentialsNonExpired, boolean accountNonLocked,
Collection<? extends GrantedAuthority> authorities, String manager, String[] directReports) {
this(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
this.manager = manager;
this.directReports = directReports;
}
public String getManager() {
return manager;
}
public String[] getDirectReports() {
return directReports;
}
}
Hope this helps.
Related
I am developing a Spring Data Rest project, and want to check for user permission when he creates or updates a resource
Here's my laptop class
#Getter
#Setter
#Entity
public class Laptop {
#Id
#GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
#Column
private String model;
#Column
private Long userId;
#PrePersist
void onCreate() {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
AppUser appUser = (AppUser) authentication.getPrincipal();
userId = appUser.getId();
}
}
Now what I want to do, is to check before user updates the laptop, to make sure that he's updating his laptop and not other's.
Here's my LaptopRepository
#RepositoryRestResource(collectionResourceRel = "content")
public interface LaptopRepository extends CrudRepository<Laptop, Long> {
#Override
//#PreAuthorize("hasPermission(#entity, 'CREATE')")
#PreAuthorize("#entity.userId == principal.id")
<S extends Laptop> S save(S entity);
}
And here's the PermissionEvaluator's method
#Override
public boolean hasPermission(Authentication authentication,
Object targetDomainObject, Object permission) {
return true;
}
Now the point is
How do I distinguish between POST and PUT methods?
If I change my #PreAuthorize to just pass the entity to the hasPermission method to just test, it always gets passes as null
As stated in the guides
import org.springframework.security.access.method.P;
...
#PreAuthorize("#c.name == authentication.name")
public void doSomething(#P("c") Contact contact);
import org.springframework.data.repository.query.Param;
...
#PreAuthorize("#n == authentication.name")
Contact findContactByName(#Param("n") String name);
Adding any of the annotations resolved the problem with null object, and I can distinguish between PUT and POST checking if target's id is null or not
I have been able to get a Spring Security based application up and running, and it has been satisfying all my requirements until now.
I do have 1 doubt regarding how UserDetailsService is used in Spring Security. I have a custom 'UserDetailsService' implementation, which goes like this -
public class CustomUserDetailsService implements UserDetailsService {
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Optional<UserDetailsDto> userDetailsByEmail = // Load userDetailsDto from database
if (!userDetailsByEmail.isPresent()) {
throw new UsernameNotFoundException("Username does not exists");
}
UserDetailsDto userDetailsDto = userDetailsByEmail.get();
List<Role> roles = roleService.listByEmail(username);
List<ModulePermission> modulePermissions = modulePermissionService.listByUserId(userDetailsDto.getId());
UserType userType = userTypeService.getByUserId(userDetailsDto.getId());
return new LoggedInUser(userDetailsDto, roles, modulePermissions, userType);
}
}
The class LoggedInUser is an extension of Spring Security's org.springframework.security.core.userdetails.User class, which goes like this -
public class LoggedInUser extends User {
private static final long serialVersionUID = -1L;
private Long userId;
private boolean firstLogin;
private UserType userType;
private List<ModulePermission> modulePermissions;
private String firstName;
private String lastName;
private String contactNo;
public LoggedInUser(UserDetailsDto userDetailsDto, List<Role> roles, List<ModulePermission> modulePermissions,
UserType userType) {
super(userDetailsDto.getEmail(), userDetailsDto.getPassword(), userDetailsDto.getEnabledStatus().getValue(),
userDetailsDto.getAccountNonExpiredStatus().getValue(), true,
userDetailsDto.getAccountNonLockedStatus().getValue(),
roles.stream().map(role -> new SimpleGrantedAuthority(role.getId())).collect(Collectors.toList()));
this.modulePermissions = modulePermissions;
this.userType = userType;
this.userId = userDetailsDto.getId();
this.firstLogin = userDetailsDto.getIsFirstLoginStatus().getValue();
this.firstName = userDetailsDto.getFirstName();
this.lastName = userDetailsDto.getLastName();
this.contactNo = userDetailsDto.getContactNo();
}
public List<ModulePermission> getModulePermissions() {
return Collections.unmodifiableList(modulePermissions);
}
public UserType getUserType() {
return userType;
}
public Long getUserId() {
return userId;
}
public boolean isFirstLogin() {
return firstLogin;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
public String getContactNo() {
return contactNo;
}
public void setFirstLogin(boolean firstLogin) {
this.firstLogin = firstLogin;
}
}
Now, to configure Spring Security to use my CustomUserDetailsService, I do the following in security configuration -
#Bean
public UserDetailsService customUserDetailsService() {
return new CustomUserDetailsService();
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.antMatcher(SuperAdminConstant.UrlConstant.ANT_MATCHER_PATH)
.userDetailsService(customUserDetailsService())
.formLogin(// further configuration)
}
And this works without any problems.
But notice that in CustomUserDetailsService, several database queries are executed even before the user has been authenticated successfully (This is because Spring Security has created a DaoAuthenticationProvider, which loads a UserDetails implementation (in my case, LoggedInUser), and perform various checks on that object AFTER it has been retrieved from a UserDetailsService (in my case , CustomUserDetailsService)).
Consider that a user has entered the correct username, but a wrong password. In that case, the high-level authentication flow would be -
CustomUserDetailsService would be called
First query is executed to verify username and load user details (UsernameNotFoundException is not thrown as username is correct)
Second query is executed to retrieve the roles
Third query is executed to retrieve module permissions
Fourth query is executed to retrieve user types
DaoAuthenticationProvider checks the password, finds it to be incorrect, and throws a BadCredentialsException.
So as can be seen, total 4 queries are executed EVEN BEFORE authentication process has completed, out of which only 1 is essential at this stage (the first query to verify username).
One solution to this problem can be to eliminate the use of UserDetailsService altogeather, and use a custom AuthenticationProvider instead.
public class CustomAuthenticationProvider implements AuthenticationProvider {
#Override
Authentication authenticate(Authentication authentication)
throws AuthenticationException {
// Customize the authentication logic here, and retrieve
// user information only if everything is correct.
}
}
But going by this approach also means that I have to duplicate code and functionality provided by DaoAuthenticationProvider and AbstractUserDetailsAuthenticationProvider, which includes checking user account status flags manually (accountNonExpired, accountNonLocked etc.), and throwing exceptions.
So I was wondering weather it is possible to perform authentication logic in such a way that user information is retrieved only AFTER authentication succeeds, and most of the authentication logic provided by Spring Security can be resused.
Any ideas will be deeply appreciated.
You can write implementation of AuthenticationSuccessHandler:
#Component
public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler {
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
LoggedInUser loggedInUser = (LoggedInUser)authentication.getPrincipal();
List<Role> roles = roleService.listByEmail(username);
List<ModulePermission> modulePermissions = modulePermissionService.listByUserId(userDetailsDto.getId());
UserType userType = userTypeService.getByUserId(userDetailsDto.getId());
// Set roles after authentication succeeds
loggedInUser.setRoles(roles);
loggedInUser.setModulePermissions(modulePermissions);
loggedInUser.setUserType(userType);
}
}
After the authentication succeeds, you can obtain logged in user from security context and set additional properties.
I need a login strategy to work with a mysql db. My user table has md5 password encryption.
I need to develop login. My code won't work. Here is my SecutiryConfig:
#Configuration
#EnableWebSecurity
#EnableGlobalAuthentication
#ComponentScan("org.ebook.*")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
#Autowired
Environment env;
#Autowired
private UserRepository userRepository;
#Autowired
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(new UserService(userRepository)).passwordEncoder(passwordEncoder());
}
#Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().antMatchers("/").hasAnyRole("USER", "ADMIN").antMatchers("/index")
.hasAnyRole("USER", "ADMIN").antMatchers("/dashboard").hasAnyRole("USER", "ADMIN")
.antMatchers("/login").hasRole("ANONYMOUS").and().formLogin().loginPage("/login")
.defaultSuccessUrl("/dashboard").usernameParameter("username")
.passwordParameter("password").and().rememberMe()
.tokenValiditySeconds(Integer.parseInt(env.getProperty("session.tokenValidity")))
.key(env.getProperty("session.key")).and().logout().logoutSuccessUrl("/login").and()
.exceptionHandling().accessDeniedPage("/403").and().csrf();
}
#Bean
public Md5PasswordEncoder passwordEncoder(){
Md5PasswordEncoder encoder = new Md5PasswordEncoder();
return encoder;
}
}
And hre is my UserService:
#Service
#Transactional(readOnly = true)
public class UserService implements UserDetailsService {
private UserRepository userRepository;
#Autowired
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
#Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
org.fingerlinks.ebook.model.bean.User user = null;
if (userRepository!=null) {
user = userRepository.findByUsername(username);
}
if (user != null) {
List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
return new User(user.getUsername(), user.getPassword(), authorities);
}
throw new UsernameNotFoundException("User '" + username + "' not found");
}
}
My problem is that user, in login page, can't login if I use passwordEncoder with an encrypted password on user table.
But if I remove encoding in java code and in user table, all work well.
Can anyone help me to understand where is the terrible mistake?
I'm using spring 4.1.6 and spring security 4.0.2.
Try this while saving user password:
Md5PasswordEncoder encoder = new Md5PasswordEncoder();
user.setPassword(encoder.encode(user.getPassword()));
Spring security encode the entered password and checks against the database password.
In your case you are storing the plain password not the encoded password in the database. Encode the password using Md5PasswordEncoder and store it in the database.
I'm writing Grails application with Spring Security plugin.
I have enabled queries generated by GORM into console and I have noticed that every request Security query the database about users, selecting them by it's username.
My intention is load user's by it's ID's, not usernames for increase performance.
I am aware that there is a possibility to overwrite UserDetailsService method loadUserByUsername(String username), but this method is used both for refreshing user's credential during the session and in login form, where in fact I want to authenticate user by it's username.
I have three questions:
How to load user by id? Should I inject user ID instead of username in GrailsUser (implementation of UserDetails) instead of regular username and use long selectById = Long.valueOf(String username)?
How to create different user provider for refreshing session to grab user by ID and different for user login (when I want to grab user by it's username/email)?
There is possibility to fetch user credentials not every request, but every X seconds?
Finally i managed to solve this problem. The queries are generated by:
springSecurityService.getCurrentUser()
Unfortunatelly, this method fetches User model class by username (from Principal object) and maps it into database field, at most configured by:
grails.plugin.springsecurity.userLookup.usernamePropertyName
as mentioned in documentation.
I have tried
grails.plugin.springsecurity.userLookup.usernamePropertyName = 'id'
but i received class-cast exception from String to Long.
Workaround is simple - create own Principle with username field typed as Long.
See PrincipalProxy in my solution:
package com.selly.util.security
import java.security.Principal;
import grails.plugin.springsecurity.userdetails.GrailsUser
import org.springframework.security.core.Authentication
import org.springframework.security.core.GrantedAuthority
class AppMetadataAuthenticationToken implements Authentication, Principal {
private boolean authenticated
private GrailsUser userDetails
private Principal principal
public AppMetadataAuthenticationToken(GrailsUser userDetails) {
this.userDetails = userDetails
this.principal = new PrincipalProxy(userDetails)
}
public GrailsUser getUser() {
return userDetails
}
public String getUsername() {
return userDetails.getUsername()
}
#Override
public String getName() {
return userDetails.getUsername()
}
#Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return userDetails.getAuthorities()
}
#Override
public Object getCredentials() {
return userDetails.password
}
#Override
public Object getDetails() {
return getUser()
}
#Override
public Object getPrincipal() {
return principal
}
#Override
public boolean isAuthenticated() {
return authenticated
}
#Override
public void setAuthenticated(boolean authenticated) throws IllegalArgumentException {
this.authenticated = authenticated
}
static class PrincipalProxy implements Principal {
GrailsUser grailsUser
Long username
public PrincipalProxy(GrailsUser grailsUser) {
this.grailsUser = grailsUser
this.username = grailsUser.id
}
#Override
public String getName() {
return grailsUser.id
}
}
}
To return this Token, just register your own AuthenticationProvider:
package com.selly.util.security;
import grails.plugin.springsecurity.SpringSecurityService
import org.springframework.security.authentication.AuthenticationProvider
import org.springframework.security.authentication.BadCredentialsException
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken
import org.springframework.security.authentication.dao.DaoAuthenticationProvider
import org.springframework.security.core.Authentication
import org.springframework.security.core.AuthenticationException
import org.springframework.security.core.userdetails.UserDetailsService
import org.springframework.security.core.userdetails.UsernameNotFoundException
public class AppUsernamePasswordAuthenticationProvider extends DaoAuthenticationProvider implements AuthenticationProvider {
SpringSecurityService springSecurityService
#Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
def token = (UsernamePasswordAuthenticationToken) authentication
def user = userDetailsService.loadUserByUsername(authentication.principal)
if(!user)
throw new UsernameNotFoundException("Cannot find user", authentication.principal)
if(!passwordEncoder.isPasswordValid(user.password, authentication.credentials, null))
throw new BadCredentialsException("Invalid password")
return new AppMetadataAuthenticationToken(user)
}
#Override
public boolean supports(Class<?> authentication) {
return UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication);
}
}
package com.selly.util.security;
import org.springframework.security.authentication.AuthenticationProvider
import org.springframework.security.core.Authentication
import org.springframework.security.core.AuthenticationException
public class AppMetadataAuthenticationProvider implements AuthenticationProvider {
#Override
public Authentication authenticate(Authentication authentication)
throws AuthenticationException {
// TODO Auto-generated method stub
return authentication;
}
#Override
public boolean supports(Class<?> authentication) {
// TODO Auto-generated method stub
return AppMetadataAuthenticationToken.class.isAssignableFrom(authentication);
}
}
Register it in resources.groovy
appUsernamePasswordAuthenticationProvider(AppUsernamePasswordAuthenticationProvider) {
userDetailsService = ref('userDetailsService')
passwordEncoder = ref('passwordEncoder')
userCache = ref('userCache')
saltSource = ref('saltSource')
preAuthenticationChecks = ref('preAuthenticationChecks')
postAuthenticationChecks = ref('postAuthenticationChecks')
springSecurityService = ref('springSecurityService')
}
And in Config.groovy:
grails.plugin.springsecurity.providerNames = [
'appMetadataAuthenticationProvider',
'appUsernamePasswordAuthenticationProvider',
// 'daoAuthenticationProvider',
// 'anonymousAuthenticationProvider',
// 'rememberMeAuthenticationProvider'
]
Now all works perfectly:
Hibernate: select this_.id as id13_0_, this_.account_expired as account2_13_0_, this_.account_locked as account3_13_0_, this_.enabled as enabled13_0_, this_."password" as password5_13_0_, this_.password_expired as password6_13_0_, this_.username as username13_0_, this_.workspace as workspace13_0_ from users this_ where (**this_.id=?**) limit ?
Instead of using getCurrentUser() you can also getPrincipal() and cast to your previously populated object with more data than Principal interface offers.
We are creating a grails aplication where we want the user to log in using their Active Directory credentials. Additionally, we want to give the business owner of this application the ability to control who has access to certain links (actions). Because of this we are using the following plugins in our grails application:
Spring Security Core
Spring Security LDAP
Spring Security UI
Because we want to empower the business user to create customized roles with certain permissions(actions) on the fly when necessary, we think that the best Spring Security Configuration is the Requestmap database based approach
So far we have accomplished as follows:
We are being able to authenticate against Active Directory successfully.
We have also been able to create different Request Mappings for different roles (ROLE_XXX) through the UI interface of the spring-security-ui plugin
Problems/Questions
The spring-security-core plugin created the following tables:
PERSON
AUTHORITY
PERSON_AUTHORITY
REQUESTMAP
These are the tables that support the creation of Roles, the assignment of URLs to roles. However, the Person_Authoritity table as the convention name implies it's a many to many relationship between a PERSON and an AUTHORITY (ROLE) since a person can potentially have more than one role. My problem is that I do not have a Person because the person already exists in Active Directory (an external source) and it was not created in the application.
Is there a way to make the authenticated user to be the PERSON ? The spring security solution requires that Person row or object however you prefer to refer to it.
I have also posted the question here:
http://grails.1312388.n4.nabble.com/Issues-integrating-LDAP-Authentication-with-Requestmap-to-Secure-URLs-td4644040.html
Thanks,
So you need to essentially map the AD user to a Person.
Here are the 3 classes you need in src/groovy. Obviously modify them as needed:
package yourpackagename
import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser
import org.springframework.security.core.GrantedAuthority
class CustomUserDetails extends GrailsUser{
final String firstName
final String lastName
CustomUserDetails(String username, String password, boolean enabled,
boolean accountNonExpired, boolean credentialsNonExpired,
boolean accountNonLocked,
Collection<GrantedAuthority> authorities,
long id, String firstName, String lastName) {
super(username, password, enabled, accountNonExpired,
credentialsNonExpired, accountNonLocked, authorities, id)
this.firstName = firstName
this.lastName = lastName
}
}
package yourpackagenamehere
import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUserDetailsService
import org.springframework.security.core.authority.GrantedAuthorityImpl
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
class CustomUserDetailsService implements GrailsUserDetailsService {
/**
* Some Spring Security classes (e.g. RoleHierarchyVoter) expect at least one role, so
* we give a user with no granted roles this one which gets past that restriction but
* doesn't grant anything.
*/
static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
UserDetails loadUserByUsername(String username, boolean loadRoles)
throws UsernameNotFoundException {
return loadUserByUsername(username)
}
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User.withTransaction { status ->
User user = User.findByUsername(username)
if (!user) throw new UsernameNotFoundException('User not found', username)
def authorities = user.authorities.collect {new GrantedAuthorityImpl(it.authority)}
return new CustomUserDetails(user.username, user.password, user.enabled,
!user.accountExpired, !user.passwordExpired,
!user.accountLocked, authorities ?: NO_ROLES, user.id,
user.firstName, user.lastName)
} as UserDetails
}
}
package yourpackagenamehere
import groovy.sql.Sql
import org.springframework.ldap.core.DirContextAdapter
import org.springframework.ldap.core.DirContextOperations
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper
import org.springframework.security.core.authority.GrantedAuthorityImpl
import org.springframework.security.core.GrantedAuthority
import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils
import org.springframework.security.core.userdetails.UsernameNotFoundException
import org.springframework.security.authentication.DisabledException
class CustomUserDetailsContextMapper implements UserDetailsContextMapper {
private static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
def dataSource
#Override
public CustomUserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authority) {
username = username.toLowerCase()
User user = User.findByUsername(username)
String firstName = ctx.originalAttrs.attrs['givenname'].values[0]
String lastName = ctx.originalAttrs.attrs['sn'].values[0]
def roles
User.withTransaction {
if(!user){
user = new User(username: username, enabled: true, firstName: firstName, lastName: lastName)
user.save(flush: true)
}
else {
user = User.findByUsername(username)
user.firstName = firstName
user.lastName = lastName
user.save(flush: true)
}
roles = user.getAuthorities()
}
if ( !user.enabled )
throw new DisabledException("User is disabled", username)
def authorities = roles.collect { new GrantedAuthorityImpl(it.authority) }
authorities.addAll(authority)
def userDetails = new CustomUserDetails(username, user.password, user.enabled, false, false, false, authorities, user.id, user.firstName, user.lastName)
return userDetails
}
#Override
public void mapUserToContext(UserDetails arg0, DirContextAdapter arg1) {
}
}
Under configuration in spring/resources.groovy :
import yourpackagenamehere.CustomUserDetailsService
import yourpackagenamehere.CustomUserDetailsContextMapper
beans = {
userDetailsService(CustomUserDetailsService)
ldapUserDetailsMapper(CustomUserDetailsContextMapper) {
dataSource = ref("dataSource")
}
}
Under Config.groovy, here are my settings:
grails.plugins.springsecurity.ldap.context.managerDn = 'CN=username,OU=People,DC=foo,DC=com'
grails.plugins.springsecurity.ldap.context.managerPassword = 'password'
grails.plugins.springsecurity.ldap.context.server = 'ldap://foo.com:389/'
grails.plugins.springsecurity.ldap.authorities.ignorePartialResultException = true
grails.plugins.springsecurity.ldap.search.base = 'ou=People,dc=foo,dc=com'
grails.plugins.springsecurity.ldap.search.filter="sAMAccountName={0}"
grails.plugins.springsecurity.ldap.search.searchSubtree = true
grails.plugins.springsecurity.ldap.auth.hideUserNotFoundExceptions = false
grails.plugins.springsecurity.ldap.search.attributesToReturn = null
grails.plugins.springsecurity.providerNames = ['ldapAuthProvider', 'anonymousAuthenticationProvider']
grails.plugins.springsecurity.ldap.mapper.userDetailsClass = 'CustomUserDetails'
grails.plugins.springsecurity.ldap.authorities.retrieveGroupRoles = true
grails.plugins.springsecurity.ldap.authorities.retrieveDatabaseRoles = true
grails.plugins.springsecurity.ldap.authorities.groupSearchBase ='dc=foo,dc=com'
grails.plugins.springsecurity.ldap.authorities.groupSearchFilter = 'member={0}'