Lost with LDAP + DB Roles

classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

Lost with LDAP + DB Roles

enTropy Fragment
Hi!

I managed to authenticate users via LDAP with the spring-security-ldap plugin.
The problem is that those users must get their Roles from the database instead of the LDAP server.

I've been reading forums, tutorials and articles for 2 days now and couldn't even get an idea of what should I do to achieve that :(

I would also like to assign a role by default. I tried to make it by setting:
grails.plugins.springsecurity.ldap.authorities.defaultRole = 'ROLE_USER'

But this throws this error:
groovy.lang.MissingPropertyException: No such property: id for class: org.springframework.security.ldap.userdetails.LdapUserDetailsImpl

I understand the way to go is in the mapping, but I don't know how to configure it properly


Any hints, please?


Thanks in advance ^^
Reply | Threaded
Open this post in threaded view
|

Re: Lost with LDAP + DB Roles

sameer.garg
Hi,
  To get the roles from LDAP add this property to Config.groovy grails.plugins.springsecurity.ldap.authorities. retrieveDatabaseRoles = false
  I am struggling to get LDAP authentication working. Since you have come across that i thought you may be able to help me. I am using grails 1.3.6 with spring-security-ldap 1.0.1 version of plugin. After installation of plugin i ran s2-quickstart to get basic scaffolding. I added my ldap configuration in config file but every time i try to login i get
springsecurity.RequestHolderAuthenticationFilter Request is to process authentication
springsecurity.RequestHolderAuthenticationFilter Authentication request failed: org.springframework.security.authentication.AuthenticationServiceException: [LDAP: error code 49 - 80090308: LdapErr: DSID-0C0903AA, comment: AcceptSecurityContext error, data 525, v1772 . Please let me know if i have not explained properly.
Thanks in advance.
Sameer
Reply | Threaded
Open this post in threaded view
|

Re: Lost with LDAP + DB Roles

Justin Rimel
In reply to this post by enTropy Fragment
By no means an expert on this stuff but we have two apps, one using ldap roles and the other using gorm roles.

What are you config.groovy settings?  Something like below?

// Added by the Spring Security Core plugin:
grails.plugins.springsecurity.userLookup.userDomainClassName = 'com.User'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'com.UserRole'
grails.plugins.springsecurity.authority.className = 'com.Role'

grails.plugins.springsecurity.roleHierarchy = RoleConstants.ROLE_DEPENDENCIES
grails.plugins.springsecurity.ldap.authorities.retrieveDatabaseRoles = true


On Fri, Feb 11, 2011 at 4:14 AM, enTropy Fragment <[hidden email]> wrote:
Hi!

I managed to authenticate users via LDAP with the spring-security-ldap plugin.
The problem is that those users must get their Roles from the database instead of the LDAP server.

I've been reading forums, tutorials and articles for 2 days now and couldn't even get an idea of what should I do to achieve that :(

I would also like to assign a role by default. I tried to make it by setting:
grails.plugins.springsecurity.ldap.authorities.defaultRole = 'ROLE_USER'

But this throws this error:
groovy.lang.MissingPropertyException: No such property: id for class: org.springframework.security.ldap.userdetails.LdapUserDetailsImpl

I understand the way to go is in the mapping, but I don't know how to configure it properly


Any hints, please?


Thanks in advance ^^

Reply | Threaded
Open this post in threaded view
|

Re: Lost with LDAP + DB Roles

enTropy Fragment

Tnx for the info. I managed to make it work just 1 minute before going back home. On monday when I get back to work I'll put here what did I do and the forum post I found helpfull. ^^

El 12/02/2011 03:38, "Justin Rimel" <[hidden email]> escribió:
Reply | Threaded
Open this post in threaded view
|

Re: Lost with LDAP + DB Roles

enTropy Fragment
The solution I found, after some hard days digging in the wild of the Internet:

If you just want to authenticate and read groups from LDAP the proper configuration in Config.groovy will be enough.
When you want to authenticate via LDAP while reading Roles from the database from users things become fishy.
The problem is LDAP manages its own UserDetails class, wich does not have the proper values (like id, for instance) so you can not retrieve roles from the database for this users.
I found the solution in the link below. Lots of thanks to them, I'd commit suicide hadn't I found the post :f

Now this is what I did to make it work, I hope it will save lots of time and pain to somebody someday:


Config.groovy
// Spring Security Core Stuff
grails.plugins.springsecurity.userLookup.userDomainClassName = 'intranet.SecUser'
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'intranet.SecUserSecRole'
grails.plugins.springsecurity.authority.className = 'intranet.SecRole'
// below we specify we want to use LDAP to authenticate users
grails.plugins.springsecurity.providerNames = ['ldapAuthProvider']


// Spring Security LDAP Stuff
grails.plugins.springsecurity.ldap.context.managerDn = 'cn=Administrador, cn=Users, dc=aula, dc=local'
grails.plugins.springsecurity.ldap.context.managerPassword = 'letmein'
grails.plugins.springsecurity.ldap.context.server = 'ldap://172.16.2.2:389'
 // It will search for groups here, we don't want groups from LDAP but we must still specify this so LDAP can authentify us. Kinda weird
grails.plugins.springsecurity.ldap.authorities.groupSearchBase = 'cn=Users,dc=aula,dc=local'
grails.plugins.springsecurity.ldap.search.base = 'cn=Users,dc=aula,dc=local'
// Set this to true if you want LDAP groups to be converted to ROLES (ex: ldap USERS becomes grails ROLE_USERS automagically)
grails.plugins.springsecurity.ldap.authorities.retrieveGroupRoles = false
// Set this to true if you want to read user roles from the app database
grails.plugins.springsecurity.ldap.authorities.retrieveDatabaseRoles = true


This is the most important class. Notice we create a new user in the database if the authentication was passed but there is no reference to this user in the database. We must do this so we can assign roles to those users later :)
Another approach would be to import all LDAP users to the App DB before starting to play with the application. The best approach will depend on your needs.
Also notice we don't save any password there, and the authentication ALWAYS takes place in the LDAP not the database.
I don't know how would this work if we want authentication for both LDAP and Database users.

CustomUserDetailsContextMapper 
class CustomUserDetailsContextMapper implements UserDetailsContextMapper {

private static final List NO_ROLES = [new GrantedAuthorityImpl(SpringSecurityUtils.NO_ROLE)]
def springSecurityService

@Override
public CustomUserDetails mapUserFromContext(DirContextOperations ctx, String username, Collection<GrantedAuthority> authority) {
SecUser user = SecUser.findByUsername(username)
if(!user){
SecUser.withTransaction(){
user = new SecUser(username: username, enabled: true)
user.save()
new SecUserSecRole(user, SecRole.findByAuthority('ROLE_USER')).save(flush: true)
}
}
def roles = user.getAuthorities()
def authorities = roles.collect { new GrantedAuthorityImpl(it.authority) }
def userDetails = new CustomUserDetails(username, user.password, user.enabled, false,
false, false, authorities, user.id, username)
return userDetails
}
@Override
public void mapUserToContext(UserDetails arg0, DirContextAdapter arg1) {
}
}


CustomUserDetails.groovy
class CustomUserDetails extends GrailsUser {

   final String fullName

   CustomUserDetails(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)

      this.fullName = fullName
   }
}


CustomUserDetailsService 
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 {

      SecUser.withTransaction { status ->

         SecUser user = SecUser.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.username)
      }
   }
}




2011/2/12 enTropy Fragment <[hidden email]>

Tnx for the info. I managed to make it work just 1 minute before going back home. On monday when I get back to work I'll put here what did I do and the forum post I found helpfull. ^^

El 12/02/2011 03:38, "Justin Rimel" <[hidden email]> escribió: