Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

JWT Refresh Token does not work with grails-spring-security-ldap #22

Open
dbaylerg opened this issue Sep 18, 2019 · 6 comments
Open

JWT Refresh Token does not work with grails-spring-security-ldap #22

dbaylerg opened this issue Sep 18, 2019 · 6 comments

Comments

@dbaylerg
Copy link

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/#" 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?

@dbaylerg
Copy link
Author

Related issue?
grails/grails-spring-security-rest#396

@amsakni
Copy link

amsakni commented Jan 24, 2020

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

@amsakni
Copy link

amsakni commented Jan 24, 2020

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.

@dbaylerg
Copy link
Author

Thank you I will try the work around

@vannakdy
Copy link

vannakdy commented Feb 2, 2023

@dbaylerg
Copy link
Author

@amsakni Apologies for the considerable time lapse but thank you for the fix. It was implemented and is working.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants