Skip to content

OAuth2 client_credentials grant type not possible in non-web spring boot service #5735

@yarodinD

Description

@yarodinD

I have a spring boot application (SB 1.3.3), configured like this:

spring:
  main:
    web-environment: false 

security:
  oauth2:
    client:
      client-id: trusted_test_client
      client-secret: Gehe1m
      access-token-uri: http://localhost:49510/v1/oauth/token

According to the spring boot 1.3.3 documentation, I should be able to @autowire and use a OAuth2RestOperations instance to access secured resources with client_credentials mechanism. The main class is only annotated with @SpringBootApplication.

During startup, I can see the following lines:

2016-04-19 14:56:53.183  INFO 26621 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'oauth2RemoteResource' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=false; factoryBeanName=demoApplication; factoryMethodName=oauth2RemoteResource; initMethodName=null; destroyMethodName=(inferred); defined in com.booxware.demo.oauth.client.DemoApplication] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2RestOperationsConfiguration$SingletonScopedConfiguration; factoryMethodName=oauth2RemoteResource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2RestOperationsConfiguration$SingletonScopedConfiguration.class]]
2016-04-19 14:56:53.184  INFO 26621 --- [           main] o.s.b.f.s.DefaultListableBeanFactory     : Overriding bean definition for bean 'oauth2RemoteResource' with a different definition: replacing [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2RestOperationsConfiguration$SingletonScopedConfiguration; factoryMethodName=oauth2RemoteResource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2RestOperationsConfiguration$SingletonScopedConfiguration.class]] with [Root bean: class [null]; scope=; abstract=false; lazyInit=false; autowireMode=3; dependencyCheck=0; autowireCandidate=true; primary=true; factoryBeanName=org.springframework.boot.autoconfigure.security.oauth2.client.OAuth2RestOperationsConfiguration$BaseConfiguration; factoryMethodName=oauth2RemoteResource; initMethodName=null; destroyMethodName=(inferred); defined in class path resource [org/springframework/boot/autoconfigure/security/oauth2/client/OAuth2RestOperationsConfiguration$BaseConfiguration.class]]''

When I try to use the OAuth2RestOperations object, I get the following Exception:

org.springframework.security.oauth2.client.resource.UserRedirectRequiredException: A redirect is required to get the users approval
    at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.getRedirectForAuthorization(AuthorizationCodeAccessTokenProvider.java:359) ~[spring-security-oauth2-2.0.9.RELEASE.jar:na]
    at org.springframework.security.oauth2.client.token.grant.code.AuthorizationCodeAccessTokenProvider.obtainAccessToken(AuthorizationCodeAccessTokenProvider.java:205) ~[spring-security-oauth2-2.0.9.RELEASE.jar:na]
    at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainNewAccessTokenInternal(AccessTokenProviderChain.java:142) ~[spring-security-oauth2-2.0.9.RELEASE.jar:na]
    at org.springframework.security.oauth2.client.token.AccessTokenProviderChain.obtainAccessToken(AccessTokenProviderChain.java:118) ~[spring-security-oauth2-2.0.9.RELEASE.jar:na]

I debugged a bit. In OAuth2RestOperationsConfiguration class, there is the following code:

    @Configuration
    protected abstract static class BaseConfiguration {

        @Bean
        @ConfigurationProperties("security.oauth2.client")
        @Primary
        public AuthorizationCodeResourceDetails oauth2RemoteResource() {
            AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
            return details;
        }

    }

    @Configuration
    @ConditionalOnNotWebApplication
    protected static class SingletonScopedConfiguration {

        @Bean
        @ConfigurationProperties("security.oauth2.client")
        @Primary
        public ClientCredentialsResourceDetails oauth2RemoteResource() {
            ClientCredentialsResourceDetails details = new ClientCredentialsResourceDetails();
            return details;
        }

        @Bean
        public DefaultOAuth2ClientContext oauth2ClientContext() {
            return new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest());
        }

    }

During startup, an AuthorizationCodeResourceDetails is created, no a ClientCredentialsResourceDetails. oauth2ClientContext() is called from the SingletonScopedConfiguration class, but oauth2RemoteResource() is called from BaseConfiguration class, not SingletonScopedConfiguration.

For me it looks like spring boot grabs the wrong configuration.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions