Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Boot OAuth2 - Could not obtain user details from token

I searched the web for solution of this problem but didn't find any working solution. I'm trying to setup basic Spring Boot OAuth2 Authorization Provider and Client.

I followed official Spring Boot instructions and created single sign on with Facebook and Github. Then i followed instructions to create Secure Spring Boot Web application.

I wanted to create my own Authorization Server so I added @EnableAuthorizationServer annotation to Secure Web Application as explained here. I also added details of an OAuth2 client as described in a link. I followed further instructions and created a OAuth2 Client.

I start both applications, visit 127.0.0.1:9999 to open a Client, client redirects me to localhost:8080/login, I enter user details and Authentication Provider redirects me to 127.0.0.1:9999/login and I get an error message:

Authentication Failed: Could not obtain user details from token

This is what gets logged:

INFO 2800 --- [nio-9999-exec-3] o.s.b.a.s.o.r.UserInfoTokenServices : Getting user info from: http:// localhost:8080/me

DEBUG 2800 --- [nio-9999-exec-3] o.s.s.oauth2.client.OAuth2RestTemplate : Created GET request for http:// localhost:8080/me

DEBUG 2800 --- [nio-9999-exec-3] o.s.s.oauth2.client.OAuth2RestTemplate : Setting request Accept header to [application/json, application/*+json]

DEBUG 2800 --- [nio-9999-exec-3] o.s.s.oauth2.client.OAuth2RestTemplate : GET request for http:// localhost:8080/me resulted in 200 (OK)

INFO 2800 --- [nio-9999-exec-3] o.s.b.a.s.o.r.UserInfoTokenServices : Could not fetch user details: class org.springframework.web.client.RestClientException, Could not extract response: no suitable HttpMessageConverter found for response type [interface java.util.Map] and content type [text/html;charset=UTF-8]]

This is my Client application:

@EnableAutoConfiguration
@Configuration
@EnableOAuth2Sso
@RestController
public class ClientApplication {
    
    @RequestMapping("/")
    public String home(Principal user) {
        return "Hello " + user.getName();
    }

    public static void main(String[] args) {
        SpringApplication.run(ClientApplication.class, args);
    }

}

This is client application YML:

server:
  port: 9999
security:
  oauth2:
    client:
      client-id: acme
      client-secret: acmesecret
      access-token-uri: http://localhost:8080/oauth/token
      user-authorization-uri: http://localhost:8080/oauth/authorize
    resource:
      user-info-uri: http://localhost:8080/me

This is my Authorization Provider application:

@SpringBootApplication
public class SecurityApp {

    public static void main(String[] args) {
        SpringApplication.run(SecurityApp.class, args);
    }

}

@Configuration
@EnableWebSecurity
@EnableAuthorizationServer
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("password").roles("USER");
    }
}

@Configuration
public class MvcConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/home").setViewName("home");
        registry.addViewController("/").setViewName("home");
        registry.addViewController("/hello").setViewName("hello");
        registry.addViewController("/login").setViewName("login");
    }

}

@RestController
public class Controller {

    @RequestMapping({ "/user", "/me" })
    public Map<String, String> user(Principal principal) {
      Map<String, String> map = new LinkedHashMap<>();
      map.put("name", principal.getName());
      return map;
    }
}

This is Application Provider YML:

security:
  oauth2:
    client:
      client-id: acme
      client-secret: acmesecret
      scope: read,write
      auto-approve-scopes: '.*'
like image 668
dplesa Avatar asked Feb 20 '16 11:02

dplesa


People also ask

What is OAuth 2.0 and how it works in spring boot?

OAuth2 is an authorization framework that enables the application Web Security to access the resources from the client. To build an OAuth2 application, we need to focus on the Grant Type (Authorization code), Client ID and Client secret.

Does spring boot support OAuth2?

Conclusion. Spring Security and Spring Boot permit to quickly set up a complete OAuth2 authorization/authentication server in an almost declarative manner. The setup can be further shortened by configuring OAuth2 client's properties directly from application. properties/yml file, as explained in this tutorial.


1 Answers

I solved the issue! I was missing the Resource Server which handles the requests for user endpoint (user-info-uri). To the Authorization Provider application I added this class:

@Configuration
@EnableResourceServer
public class ResourceServer
        extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
            .antMatcher("/me")
            .authorizeRequests().anyRequest().authenticated();
    }
}
like image 133
dplesa Avatar answered Sep 19 '22 06:09

dplesa