Skip to content
New issue

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

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

Already on GitHub? Sign in 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/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?

@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.

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

No branches or pull requests

3 participants