LDAP Authentication and DB authorisation with Grails Spring Security

Recently I faced quite simple problem – allow application to authenticate users via LDAP but authorise them via database. It is a common solution – we make sure that only company’s users are logging into app, but there comes flexibility with ACL stored locally. In Grails it looked pretty simple until I started to integrate this solution into my application. It took me a while to put everything together so I decided to share it.

To make long things short – there is an offical documentation but IMHO, it should be tweaked a little to be more user-friendly. The most important thing to understand are sides and roles that take place in logging process. There is LDAP instance, where we send requests to authorise user. LDAP response must be transmitted to our app and full our users’ object. Meanwhile there is also roles read from database. In addition there is simple check – if logging user has no account in our app, we will create it with default roles.

My app uses simple domain classes provided by Spring Security (User, Role and UserRole). If You are not familiar with them I suggest reading official docs. First we create UserMappingDetails class, which is simple POJO that will store user data (login, password, account data) and authorities (roles that user has).

class ChlebikUserDetails extends GrailsUser {

   ChlebikUserDetails(String username, String password, boolean enabled,
                 boolean accountNonExpired, boolean credentialsNonExpired,
                 boolean accountNonLocked,
                 Collection<GrantedAuthority> authorities,
                 long id, String fullName) {
      super(username, password, enabled, accountNonExpired,
            credentialsNonExpired, accountNonLocked, authorities, id)      

Next we create mapping class, which will translate LDAP response to our application user.

class ChlebikUserDetailsContextMapper implements UserDetailsContextMapper {

	private static final List NO_ROLES = [new SimpleGrantedAuthority(SpringSecurityUtils.NO_ROLE)]
	public ChlebikUserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<SimpleGrantedAuthority> authority) {
		User user = User.findByUsername(username)
		if(!user) {					
				// Create new user and save to the database                                
				user = new User()
				user.username = username				
				user.password = "123" // doesn't matter
				user.save(flush: true, failOnError: true)
				UserRole userRole = new UserRole()
				userRole.user = user
				userRole.role = Role.findByAuthority('USER') // Default role in my app
				userRole.save(flush: true, failOnError: true)			
		def authorities = user.getAuthorities().collect { new SimpleGrantedAuthority(it.authority) }		
		def userDetails = new ChlebikUserDetails(username, user.password, user.enabled, false,
					false, false, authorities, user.id, username)
		return userDetails

	public void mapUserToContext(UserDetails arg0, DirContextAdapter arg1) {}	

Ok, we are getting closer. Last class to create is service that will be called by Spring Security to retrieve our user when needed. It cannot be put in Grails’ service directory!!! Just place it in src/groovy

class PrePopulateUserDetailsService implements GrailsUserDetailsService  {
	Logger logger = Logger.getLogger(getClass())
	LdapUserDetailsService ldapUserDetailsService
	static final List NO_ROLES = [new SimpleGrantedAuthority(SpringSecurityUtils.NO_ROLE)]
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException {
		return loadUserByUsername(username, true)
	@Transactional	// Services in Grails are transactional by default but it is normal class so we put this annotation
	public UserDetails loadUserByUsername(String username, boolean loadRoles) throws UsernameNotFoundException, DataAccessException {
		User user = User.findByUsername(username)
		def authorities = user.getAuthorities().collect {new SimpleGrantedAuthority(it.authority)}
		return new ChlebikUserDetails(user.username, user.password, user.enabled,
			!user.accountExpired, !user.passwordExpired,
			!user.accountLocked, authorities ?: NO_ROLES, user.id,

That’s all. Of course we need to add some config to our application. First we visit configuration folder and spring subfolder. There in resources.groovy we put this (registering beans):

beans = {		

And in out Config.groovy (or whatever user-defined config file You are using) we should have several config properties. I am putting them all (to allow Grails connect to LDAP).

grails.plugin.springsecurity.providerNames = ['rememberMeAuthenticationProvider', 'ldapAuthProvider', 'anonymousAuthenticationProvider']

// Probably better to keep this data in an external file for security reasons
grails.plugin.springsecurity.ldap.context.managerDn = ''
grails.plugin.springsecurity.ldap.context.managerPassword = ''
grails.plugin.springsecurity.ldap.context.server = ''

grails.plugin.springsecurity.ldap.authorities.ignorePartialResultException = true // typically needed for Active Directory
grails.plugin.springsecurity.ldap.search.base = 'CN=putwhatyoumust,O=putwhatyoumust'
grails.plugin.springsecurity.ldap.search.searchSubtree = true
grails.plugin.springsecurity.ldap.auth.hideUserNotFoundExceptions = false

// These are crucial for LDAP/DB configuration
grails.plugin.springsecurity.ldap.authorities.retrieveGroupRoles = false
grails.plugin.springsecurity.ldap.authorities.retrieveDatabaseRoles = true

And it magically works. Above code is the result of several hours on the web. Below I put all links that helped me a lot.

Grails passwords salted
Juan Vazquez GitHub
Most helpfull Nabble
Customizing authentication in your grails app
Official plugin page


8 thoughts on “LDAP Authentication and DB authorisation with Grails Spring Security

  1. varun


    Can you please explain why is the class PrePopulateUserDetailsService needed, is it necessary?


  2. chlebik Post author

    As I’ve written – it is used by Spring Security when a call for a currently logged user is needed. It must be put outside Grails’ services folder and must be registered as a bean.

  3. Jorge

    Hi Chlebik,

    Could you write the necessary imports for the classes?

    When I write, for example:

    import org.codehaus.groovy.grails.plugins.springsecurity.GrailsUser
    it says: “unable to resolve class”.

    And that happens with GrantedAuthority, DirContextAdapter and so on.

    I don´t know if I have wroten the wrong package..

    Anyway, thanks for share your solution!

  4. chlebik Post author

    Hmmm, it must be something with Your IDE. All necessary imports were handled by Eclipse and I had no problems with them. But due to StackOverflow question You’ve asked I updated my post. Thx for the feedback.

  5. tomek

    how can i add file to /src/groovy, then they are not visible in resources.groovy even if i place them in same package

  6. tomek

    and why Logger is needed when You are not ussing it in PrePopulateUserDetailsService calss

  7. Jasen

    Thank you for this example. I’m in the process of converting an app from using internal User domain class authentication to LDAP. Unlike the example, I’ll be tracking groups in LDAP, too.
    I had it working with no local User object, but I have domain classes with a User member (e.g. comments are createdBy a User) so I think I need a User object – and the ContextMapper.
    I’ll be adding access control lists, too! (e.g. only certain users can see certain comments.)
    Definitely some very tricky low-level programming for Grails.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s