2 Usage - Reference Documentation
Authors: Burt Beckwith
Version: 1.0.6
2 Usage
Configuring your LDAP server is beyond the scope of this document. There are many different approaches and this will most likely be done by IT staff. It's assumed here that you already have a running LDAP or Active Directory server.There isn't much that you need to do in your application to use LDAP. Just install this plugin, and configure any required parameters and whatever optional parameters you want in Config.groovy. These are described in detail in Chapter 3 but typically you only need to set these properties
grails.plugins.springsecurity.ldap.context.managerDn = 'uid=admin,ou=system' grails.plugins.springsecurity.ldap.context.managerPassword = 'secret' grails.plugins.springsecurity.ldap.context.server = 'ldap://localhost:10389' grails.plugins.springsecurity.ldap.authorities.groupSearchBase = 'ou=groups,dc=yourcompany,dc=com' grails.plugins.springsecurity.ldap.search.base = 'dc=yourcompany,dc=com'
grails.plugins.springsecurity.ldap.authorities.retrieveDatabaseRoles = true
grails.plugins.springsecurity.password.algorithm = 'SHA-256'
Sample Config.groovy settings for Active Directory
Active directory is somewhat different although still relatively painless if you know what you are doing. Use these example configuration options to get started (tested in Windows Server 2008):Replace the placeholders inside brackets with appropriate values and remove the chars
// LDAP config grails.plugins.springsecurity.ldap.context.managerDn = '[distinguishedName]' grails.plugins.springsecurity.ldap.context.managerPassword = '[password]' grails.plugins.springsecurity.ldap.context.server = 'ldap://[ip]:[port]/' grails.plugins.springsecurity.ldap.authorities.ignorePartialResultException = true // typically needed for Active Directory grails.plugins.springsecurity.ldap.search.base = '[the base directory to start the search. usually something like dc=mycompany,dc=com]' grails.plugins.springsecurity.ldap.search.filter="sAMAccountName={0}" // for Active Directory you need this grails.plugins.springsecurity.ldap.search.searchSubtree = true grails.plugins.springsecurity.ldap.auth.hideUserNotFoundExceptions = false grails.plugins.springsecurity.ldap.search.attributesToReturn = ['mail', 'displayName'] // extra attributes you want returned; see below for custom classes that access this data grails.plugins.springsecurity.providerNames = ['ldapAuthProvider', 'anonymousAuthenticationProvider'] // specify this when you want to skip attempting to load from db and only use LDAP// role-specific LDAP config grails.plugins.springsecurity.ldap.useRememberMe = false grails.plugins.springsecurity.ldap.authorities.retrieveGroupRoles = true grails.plugins.springsecurity.ldap.authorities.groupSearchBase ='[the base directory to start the search. usually something like dc=mycompany,dc=com]' // If you don't want to support group membership recursion (groups in groups), then use the following setting // grails.plugins.springsecurity.ldap.authorities.groupSearchFilter = 'member={0}' // Active Directory specific // If you wish to support groups with group as members (recursive groups), use the following grails.plugins.springsecurity.ldap.authorities.groupSearchFilter = '(member:1.2.840.113556.1.4.1941:={0})' // Active Directory specific
Custom UserDetailsContextMapper
There are three options for mapping LDAP attributes toUserDetails
data (as specified by the grails.plugins.springsecurity.ldap.mapper.userDetailsClass
config attribute) and hopefully one of those will be sufficient for your needs. If not, it's easy to implement UserDetailsContextMapper yourself.Create a class in src/groovy
or src/java
that implements UserDetailsContextMapper and register it in grails-app/conf/spring/resources.groovy
:import com.mycompany.myapp.MyUserDetailsContextMapperbeans = {
ldapUserDetailsMapper(MyUserDetailsContextMapper) {
// bean attributes
}
}
UserDetailsContextMapper
that extracts three additional fields from LDAP (fullname, email, and title)package com.mycompany.myappimport org.springframework.ldap.core.DirContextAdapter import org.springframework.ldap.core.DirContextOperations import org.springframework.security.core.userdetails.UserDetails import org.springframework.security.ldap.userdetails.UserDetailsContextMapperclass MyUserDetailsContextMapper implements UserDetailsContextMapper { UserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection authorities) { String fullname = ctx.originalAttrs.attrs['name'].values[0] String email = ctx.originalAttrs.attrs['mail'].values[0].toString().toLowerCase() String username = ctx.originalAttrs.attrs['samaccountname'].values[0].toString().toLowerCase() def title = ctx.originalAttrs.attrs['title'] new MyUserDetails(username, null, true, true, true, true, authorities, fullname, email, title == null ? '' : title.values[0]) { } void mapUserToContext(UserDetails user, DirContextAdapter ctx) { throw new IllegalStateException("Only retrieving data from AD is currently supported") } }
UserDetails
class to hold the extra fields:package com.mycompany.myappimport org.springframework.security.core.GrantedAuthority import org.springframework.security.core.userdetails.Userclass MyUserDetails extends User { // extra instance variables final String fullname final String email final String title MyUserDetails(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<GrantedAuthority> authorities, String fullname, String email, String title) { super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities) this.fullname = fullname this.email = email this.title = title } }
User
class for convenience, but you could also directly implement the interface or use a different base class.