Skip to content

How can I exclude the configuration enabled through a Boot protected inner configuration class? #5427

Closed
@nucatus

Description

@nucatus

I have a concrete situation where I want to exclude the configuration implemented by
org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerTokenServicesConfiguration$JwtTokenServicesConfiguration

I tried both exclude = {ResourceServerTokenServicesConfiguration.class} and excludeName = {"org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerTokenServicesConfiguration$JwtTokenServicesConfiguration"} but none is working.

The scenario is that I want to implement my own ResourceServerTokenServices but when the upstream beans have to autowire this bean, I get this error:

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.security.oauth2.provider.token.TokenStore] is defined: expected single matching bean but found 2: customJwtTokenStore,jwtTokenStore
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1126) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1014) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:545) ~[spring-beans-4.2.5.RELEASE.jar:4.2.5.RELEASE]
    ... 19 common frames omitted

Clearly, the boot JwtTokenServicesConfiguration configuration is not omitted. There would be a hack here where I can make the JwtTokenCondition fail, but this is a low hack.

Here is the simple configuration that I'm using:

@SpringBootApplication
@EnableAutoConfiguration(exclude = {ResourceServerTokenServicesConfiguration.class},
        excludeName = {"org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerTokenServicesConfiguration$JwtTokenServicesConfiguration"})
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true, proxyTargetClass = true)
public class Elephant
{
    public static void main(String[] args) {
        SpringApplication.run(Elephant.class, args);
    }

    @Configuration
    @EnableResourceServer
    protected static class SecurityConfiguration extends ResourceServerConfigurerAdapter
    {

        @Autowired
        @Qualifier("customJwtTokenEnhancer")
        JwtAccessTokenConverter customJwtTokenEnhancer;

        @Autowired
        @Qualifier("customJwtTokenStore")
        TokenStore customJwtTokenStore;

        @Autowired
        @Qualifier("customJwtTokenServices")
        ResourceServerTokenServices customJwtTokenServices;

        @Override
        public void configure(ResourceServerSecurityConfigurer resources) throws Exception
        {
            resources.tokenServices(customJwtTokenServices);
        }

        @Bean
        public ResourceServerTokenServices customJwtTokenServices() {
            DefaultTokenServices services = new DefaultTokenServices();
            services.setTokenStore(customJwtTokenStore);
            return services;
        }

        @Bean
        public TokenStore customJwtTokenStore() {
            return new JwtTokenStore(customJwtTokenEnhancer);
        }

        @Bean
        @Autowired
        public JwtAccessTokenConverter customJwtTokenEnhancer(
                @Value("${security.oauth2.resource.jwt.keyValue}") String keyValue) {
            JwtAccessTokenConverter converter = new JwtAccessTokenConverter(){
                @Override
                public OAuth2Authentication extractAuthentication(Map<String, ?> map)
                {
                    OAuth2Authentication authentication = super.extractAuthentication(map);
                    Map<String, String> details = new HashMap<>();
                    details.put("account_id", (String) map.get("account_id"));
                    authentication.setDetails(details);
                    return authentication;
                }
            };
            if (keyValue != null) {
                converter.setVerifierKey(keyValue);
            }
            return converter;
        }
    }
}

this is the configuration file:

server.port = 8081

logging.level.org.springframework.security=DEBUG
security.sessions=stateless
security.oauth2.resource.jwt.keyValue=-----BEGIN PUBLIC KEY-----[[MY KEY]]-----END PUBLIC KEY-----

and the dependencies:

dependencyManagement {
    imports {
        mavenBom "org.springframework.boot:spring-boot-starter-parent:1.3.3.RELEASE"
    }
}

dependencies {
    compile('org.springframework.boot:spring-boot-starter-jdbc')
    compile('org.springframework.boot:spring-boot-starter-security')
    compile('org.springframework.boot:spring-boot-starter-web')
    compile('net.sf.ehcache:ehcache:2.10.1')

    compile("org.springframework.security:spring-security-acl:4.0.3.RELEASE")
    compile('org.springframework.security.oauth:spring-security-oauth2:2.0.9.RELEASE')
    compile('org.springframework.security:spring-security-jwt')

    compile('org.json:json:20150729')
    compile('org.apache.commons:commons-lang3:3.1')
    runtime('mysql:mysql-connector-java')

    testCompile('org.springframework.boot:spring-boot-starter-test')
    testCompile('org.testng:testng:6.9.8')
    testCompile('org.hamcrest:hamcrest-all:1.3')
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: declinedA suggestion or change that we don't feel we should currently apply

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions