Oleksandr H
Oleksandr H

Reputation: 3015

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

I try to modify existing example - Tonr2 and Sparklr2. Also I viewed this tutorial based on Spring Boot Spring Boot OAuth2. I try to build application like in Tonr2 example but without first login (on tonr2). I just need one Authentication on Sparklr2 side. I do this:

@Bean
    public OAuth2ProtectedResourceDetails sparklr() {
        AuthorizationCodeResourceDetails details = new AuthorizationCodeResourceDetails();
        details.setId("sparklr/tonr");
        details.setClientId("tonr");
        details.setTokenName("oauth_token");
        details.setClientSecret("secret");
        details.setAccessTokenUri(accessTokenUri);
        details.setUserAuthorizationUri(userAuthorizationUri);
        details.setScope(Arrays.asList("openid"));
        details.setGrantType("client_credentials");
        details.setAuthenticationScheme(AuthenticationScheme.none);
        details.setClientAuthenticationScheme(AuthenticationScheme.none);
        return details;
    }

But I have Authentication is required to obtain an access token (anonymous not allowed) . I checked this question. Of course, my user is anonymous - I want to login on Sparklr2. Also, I tried different combinations of settings of this bean, but nothing good. How to fix it? How to make it work as I want?

Upvotes: 9

Views: 6349

Answers (2)

user1206747
user1206747

Reputation: 111

Old post...

The exception indeed is thrown form AccessTokenProviderChain but it happens when spring security filters invoking if incorrect order. Make sure that your OpenIdAuthenticationFilter is invoking after OAuth2ClientContextFilter.

Upvotes: 0

user2829759
user2829759

Reputation: 3512

Almost two years late for the post.

The exception is thrown from AccessTokenProviderChain

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();

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

You either

  • Use ClientCredentialsResourceDetails in your OAuth2RestTemplate, or
  • Authenticate the user before using AuthorizationCodeResourceDetails to access external resources

In fact, in the tonr2 and sparklr2 example (I personally find the name very confusing), to access resources on sparklr2, a user has to first authenticate on tonr2. As seen in oauth2/tonr:

@Override

protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication().withUser("marissa").password("wombat").roles("USER").and().withUser("sam")
            .password("kangaroo").roles("USER");
}

If your user is anonymous, you might want to check for Single Sign On.

For whoever just want to quickly try out Oauth2 integration, add basic auth to your application:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
        .anyRequest().authenticated().and().httpBasic();
}

application.properties:

spring.security.user.password=password
spring.security.user.name=user

Don't forget to add spring-boot-starter-security to your project.

e.g. In gradle: compile 'org.springframework.boot:spring-boot-starter-security'

Or you can also disable AnonymousAuthenticationToken from creating by:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.anonymous().disable();
}

Upvotes: 2

Related Questions