Open dbaylerg opened 5 years ago
work around:
import grails.plugin.springsecurity.ldap.userdetails.GrailsLdapUserDetailsManager
import grails.plugin.springsecurity.userdetails.GrailsUserDetailsService
import groovy.transform.CompileStatic
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.ldap.core.ContextSource
import org.springframework.ldap.core.DirContextOperations
import org.springframework.security.core.GrantedAuthority
import org.springframework.security.core.userdetails.UserDetails
import org.springframework.security.ldap.search.LdapUserSearch
import org.springframework.security.ldap.userdetails.LdapAuthoritiesPopulator
import org.springframework.security.ldap.userdetails.UserDetailsContextMapper
@CompileStatic
class LdapUserDetailsManagerImpl extends GrailsLdapUserDetailsManager implements GrailsUserDetailsService {
private final Log logger = LogFactory.getLog(LdapUserDetailsManagerImpl.class)
@Autowired
private LdapAuthoritiesPopulator authoritiesPopulator
@Autowired
private LdapUserSearch userSearch;
@Autowired
private UserDetailsContextMapper ldapUserDetailsMapper;
LdapUserDetailsManagerImpl(ContextSource contextSource) {
super(contextSource)
}
private Collection<? extends GrantedAuthority> loadUserAuthorities(
DirContextOperations userData, String username) {
return authoritiesPopulator.getGrantedAuthorities(userData, username)
}
@Override
UserDetails loadUserByUsername(String username) {
logger.debug("Loading user '" + username)
DirContextOperations userFromSearch = userSearch.searchForUser(username)
List<GrantedAuthority> authorities = (List<GrantedAuthority>) loadUserAuthorities(userFromSearch, username).toList()
return ldapUserDetailsMapper.mapUserFromContext(userFromSearch, username, authorities)
}
}
inject bean in Application:
@Override
Closure doWithSpring() {
{ ->
userDetailsService(LdapUserDetailsManagerImpl)
}
}
or in resources.groovy
It is indeed a grails issue, as I understand it: GormUserDetailsManager instance is by default injected even if you are using LDAP. Injecting GrailsLdapUserDetailsManager instead doesn't work because LDAP configuration isn't injected correctly.
Thank you I will try the work around
@amsakni Apologies for the considerable time lapse but thank you for the fix. It was implemented and is working.
grails 3.3.10
application.yml grails: plugin: springsecurity: ldap: context: managerDn: 'uid=admin,ou=system' managerPassword: 'secret' server: 'ldap://myldap' authorities: groupSearchBase: 'ou=Groups,ou=TPS,dc=example,dc=com' search: base: 'ou=Users,ou=TPS,dc=example,dc=com' rest: token: storage: jwt: secret: 'myjwttokensecret'
build.gradle compile 'org.grails.plugins:spring-security-core:3.2.3' compile "org.grails.plugins:spring-security-rest:2.0.0.RC1" compile 'org.grails.plugins:spring-security-ldap:3.0.2'
I am using JWT Token generation from org.grails.plugins:spring-security-rest after authenticating with Apache Directory Server.
I use the login endpoint "/api/login" to get a JWT token which works.
I use the validate endpoint "/api/validate" to validate the JWT Token which also works.
The problem is the "/oauth/access_token" endpoint always returns 403 because an exception is thrown.
Here is what I believe to be the issues:
line 55 in grails.plugin.springsecurity.rest.token.storage.jwt.JwtTokenStorageService is "UserDetails principal = userDetailsService.loadUserByUsername(jwt.JWTClaimsSet.subject)"
The userDetailsService that is injected is an instance of GormUserDetailsManager when I would have expected to be an instance of GrailsLdapUserDetailsManager or some other LDAP implementation.
Is this something this Ldap Plugin should be injecting?