Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Oaut2RestTemplate with client_credentials error (anonymous not allowed)

I'm trying to access a web service which is protected by Spring Security using ResourceServerConfigurerAdapter (with Oauth2 client_credentials)

Following is the security configuration

//Micoservice 1
@Configuration
@EnableResourceServer
class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    @Autowired
    private Environment env;

    @Autowired
    private DummyUserFilter dummyUserFilter;

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.addFilterAfter(dummyUserFilter, LogoutFilter.class)
            .formLogin().disable()
            .httpBasic().disable()
            .csrf().disable()
            .antMatcher("/**")
            .authorizeRequests()
            .antMatchers("/js/**", "/webjars/**").permitAll()
            .anyRequest()
                .authenticated();
    }
}

This application (Microservice 1) is to be accessed by another application (Microservice 2) with the Oauth2RestTemplate. Following is the Oauth2RestTemplate configuration.

//MicroService 2
@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() {
        ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
        resourceDetails.setAccessTokenUri("https://<UAA>/oauth/token");
        resourceDetails.setClientId("#####");
        resourceDetails.setClientSecret("#####");
        resourceDetails.setGrantType("client_credentials");
        resourceDetails.setTokenName("access_token");

        DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();

        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);

        return restTemplate;
    }
}

Microservice 2 has various web services which use RestTemplate to access the protected web services of Microservice 1.

This always results in following exception

Authentication is required to obtain an access token (anonymous not allowed)

I have searched for this error and found that it's thrown in AccessTokenProviderChain

Here's the link from github for the relevant code

https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/main/java/org/springframework/security/oauth2/client/token/AccessTokenProviderChain.java#L89

if (auth instanceof AnonymousAuthenticationToken) {
    if (!resource.isClientOnly()) {
        throw new InsufficientAuthenticationException(
                "Authentication is required to obtain an access token (anonymous not allowed)");
    }
}

It seems that it doesn't allow anonymous user to get access to the Oauth2 token.

I have no intention of protecting the client application (Microservice 2) with Oauth2 and I must use client_credentials for the Oauth2RestTemplate, that's preconfigured.

How can I stop Spring from blocking anonymous user from accessing token ?

I have already tried to populate SecurityContextHolder with dummy authentication in case of anonymouse user, with no success. Even if I do succeed in doing so, it seems like a hack.

like image 582
11thdimension Avatar asked May 09 '17 01:05

11thdimension


People also ask

What is OAuth2RestTemplate?

The main goal of the OAuth2RestTemplate is to reduce the code needed to make OAuth2-based API calls. It basically meets two needs for our application: Handles the OAuth2 authentication flow. Extends Spring RestTemplate for making API calls.

What is OAuth2AuthorizedClientRepository?

OAuth2AuthorizedClientRepository: is a container class that holds and persists authorized clients between requests. The default implementation, InMemoryOAuth2AuthorizedClientService , simply stores the clients in memory.

When to use client credentials flow?

The Client Credentials grant type is used by clients to obtain an access token outside of the context of a user. This is typically used by clients to access resources about themselves rather than to access a user's resources.

How do I use Spring Security OAuth2 client?

To use GitHub's OAuth 2.0 authentication system for login, you must first Add a new GitHub app. Select "New OAuth App" and then the "Register a new OAuth application" page is presented. Enter an app name and description. Then, enter your app's home page, which should be http://localhost:8080, in this case.


2 Answers

I had the same problem and concluded that the AccessTokenProvider interface, which has multiple implementors is the culprit. By default, the OAuth2RestTemplate instantiates the AccessTokenProviderChain which tries to re-use the existing login context. However, if no such login exists, this is bound to fail. Try

restTemplate.setAccessTokenProvider(new ResourceOwnerPasswordAccessTokenProvider());

in your factory method. This uses a token provider which owns its credentials and doesn't reference the thread local SecurityContextHolder in its implementation at all.

like image 72
Yasammez Avatar answered Oct 23 '22 10:10

Yasammez


Try Enabling httpBasic() security in your 2nd microservice and login to it using default username ("user") and generated password by spring.

like image 20
Chatura Galagama Avatar answered Oct 23 '22 11:10

Chatura Galagama