Matthias
Matthias

Reputation: 1448

Spring Boot 2.0 OAuth2 Authorization Server with Ressource Server

I tried to create an authrorization server with its own login page and a resource with Spring Boot 2.0.0 and spring-security-oauth2 2.3.0. Unfortunately, the configuration of the resource server does not seem to work. With

curl -v localhost:8080/sample

always a redirect 302 to localhost:8080/login with or without token.

My Security Configuration is

@Configuration
public class SecurityConfiguration {

   @Configuration
   @Order(1)
   @EnableWebSecurity(debug = true)
   protected static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

      @Override
      protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
         auth.inMemoryAuthentication().withUser("john").password("{noop}123").roles("User");
      }

      @Override
      @Bean
      public AuthenticationManager authenticationManagerBean() throws Exception {
         return super.authenticationManagerBean();
      }

      @Override
      protected void configure(final HttpSecurity http) throws Exception {
         http.authorizeRequests()
         .antMatchers("/ping").permitAll()
         .antMatchers("/login").permitAll()
         .anyRequest().authenticated()
         .and()
         .csrf()
         .and()
         .formLogin()
         .usernameParameter("username")
         .passwordParameter("password")
         .loginPage("/login")
         .permitAll()
               .and()
               .rememberMe()
               .rememberMeParameter("remember")
         .and()
         .httpBasic().disable()
         .logout().permitAll();
      }
   }

   @Configuration
   @EnableResourceServer
   @Order(10)
   protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

      private static final String RESOURCE_ID = "Sample";

      @Override
      public void configure(final ResourceServerSecurityConfigurer resources) throws Exception {
         resources.resourceId(RESOURCE_ID);
      }

      @Override
      public void configure(final HttpSecurity http) throws Exception {
         http.authorizeRequests()
         .antMatchers("/sample**").authenticated();
      }
   }

   @Configuration
   @EnableAuthorizationServer
   @Order(Ordered.HIGHEST_PRECEDENCE)
   protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

      @Autowired
      private AuthenticationManager authenticationManager;

      @Override
      public void configure(final AuthorizationServerSecurityConfigurer security) throws Exception {
         security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
      }

      @Override
      public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
         clients.inMemory().withClient("ABC").secret("{noop}sec1").autoApprove(true)
         .authorizedGrantTypes("authorization_code", "client_credentials", "password", "refresh_token")
         .scopes("read", "write")
         .redirectUris("http://google.com");
      }

      @Override
      public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
         endpoints
         .tokenStore(new InMemoryTokenStore())
         .authenticationManager(authenticationManager);
      }

   }
}

How can I configure the resource server correctly?

Download Example Project

UPDATE:

I tested the follow configuration with Spring Boot 1.5.10, spring-security-oauth2 2.0.14 and Spring Boot 2.0.0, spring-security-oauth2 2.3.0.

With 1.5.10 it works fine but with 2.0.0 i getting "There was an unexpected error (type=Method Not Allowed, status=405)." on processing login. I see that UsernamePasswordAuthenticationFilter is missing in the security filter chain.

Is there a breaking change in Spring Boot 2.0.0 or Spring Security 5.0.3 that i missed?

@Configuration
@EnableWebMvc
@EnableAuthorizationServer
@EnableResourceServer
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfiguration {


   @Configuration
   protected static class WebMvcConfiguration extends WebMvcConfigurerAdapter implements WebMvcConfigurer {

      @Override
      public void addViewControllers(final ViewControllerRegistry registry) {
         registry.addViewController("/login").setViewName("login");
         registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
      }

   }

   @Configuration
   protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

      private static final String RESOURCE_ID = "Sample";

      @Override
      public void configure(final ResourceServerSecurityConfigurer resources) throws Exception {
         resources.resourceId(RESOURCE_ID);
      }

      @Override
      public void configure(final HttpSecurity http) throws Exception {
         http
         .authorizeRequests()
         .antMatchers("/sample**").authenticated()
         ;
      }
   }

   @Configuration
   protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

      @Autowired
      private AuthenticationManager authenticationManager;

      @Override
      public void configure(final AuthorizationServerSecurityConfigurer security) throws Exception {
         security
         .tokenKeyAccess("permitAll()")
         .checkTokenAccess("isAuthenticated()")
         ;
      }

      @Override
      public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
         clients
         .inMemory()
         .withClient("ABC")
         .secret("{noop}sec1")
         .autoApprove(true)
         .authorizedGrantTypes("authorization_code", "client_credentials", "password", "refresh_token")
         .scopes("read", "write")
         .redirectUris("http://google.com")
         ;
      }

      @Override
      public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
         endpoints
         .tokenStore(new InMemoryTokenStore())
         .authenticationManager(authenticationManager);
      }

   }


   @Configuration
   protected static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

      @Override
      protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
         auth
               .inMemoryAuthentication()
               .withUser("john")
               .password("{noop}123")
               .roles("User");
      }

      @Override
      @Bean
      public AuthenticationManager authenticationManagerBean() throws Exception {
         return super.authenticationManagerBean();
      }

      @Override
      protected void configure(final HttpSecurity http) throws Exception {
         http
         .requestMatchers()
         .antMatchers("/ping")
         .antMatchers("/login")
         .antMatchers("/oauth/**")
         .and()
         .authorizeRequests()
         .antMatchers("/ping").permitAll()
         .anyRequest().authenticated()
         .and()
         .csrf()
         .and()
         .formLogin()
         .usernameParameter("username")
         .passwordParameter("password")
         .loginPage("/login")
         .permitAll()
         .and()
         .rememberMe()
         .rememberMeParameter("remember")
         .and()
         .httpBasic().disable()
         .logout().permitAll();

      }
   }
}

Upvotes: 0

Views: 6149

Answers (2)

user663381
user663381

Reputation:

Wrote a bare-bones spring boot 2 oauth2 resource server with authorization server, putting it here in case anyone is looking for a bootstrap project:

https://github.com/indrekru/spring-boot-2-oauth2-resource-server

Upvotes: 0

Matthias
Matthias

Reputation: 1448

Thanks to dur's comments, the problem is solved.

This configuration is working:

@Configuration
@EnableWebMvc
@EnableAuthorizationServer
@EnableResourceServer
@EnableWebSecurity(debug = true)
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
public class SecurityConfiguration {


   @Configuration
   protected static class WebMvcConfiguration implements WebMvcConfigurer {

      @Override
      public void addViewControllers(final ViewControllerRegistry registry) {
         registry.addViewController("/login").setViewName("login");
         registry.setOrder(Ordered.HIGHEST_PRECEDENCE);
      }

   }

   @Configuration
   @Order(2)
   protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

      private static final String RESOURCE_ID = "Sample";

      @Override
      public void configure(final ResourceServerSecurityConfigurer resources) throws Exception {
         resources.resourceId(RESOURCE_ID);
      }

      @Override
      public void configure(final HttpSecurity http) throws Exception {
         http
         .authorizeRequests()
         .antMatchers("/sample**").authenticated()
         ;
      }
   }

   @Configuration
   protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {

      @Autowired
      private AuthenticationManager authenticationManager;

      @Override
      public void configure(final AuthorizationServerSecurityConfigurer security) throws Exception {
         security
         .tokenKeyAccess("permitAll()")
         .checkTokenAccess("isAuthenticated()")
         ;
      }

      @Override
      public void configure(final ClientDetailsServiceConfigurer clients) throws Exception {
         clients
         .inMemory()
         .withClient("ABC")
         .secret("{noop}sec1")
         .autoApprove(true)
         .authorizedGrantTypes("authorization_code", "client_credentials", "password", "refresh_token")
         .scopes("read", "write")
         .redirectUris("http://google.com")
         ;
      }

      @Override
      public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
         endpoints
         .tokenStore(new InMemoryTokenStore())
         .authenticationManager(authenticationManager);
      }

   }


   @Configuration
   @Order(1)
   protected static class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

      @Override
      protected void configure(final AuthenticationManagerBuilder auth) throws Exception {
         auth
         .inMemoryAuthentication()
         .withUser("john")
         .password("{noop}123")
         .roles("User");
      }

      @Override
      @Bean
      public AuthenticationManager authenticationManagerBean() throws Exception {
         return super.authenticationManagerBean();
      }

      @Override
      protected void configure(final HttpSecurity http) throws Exception {
         http
         .requestMatchers()
         .antMatchers("/ping")
         .antMatchers("/login")
         .antMatchers("/oauth/**")
         .and()
         .authorizeRequests()
         .antMatchers("/ping").permitAll()
         .anyRequest().authenticated()
         .and()
         .csrf()
         .and()
         .formLogin()
         .usernameParameter("username")
         .passwordParameter("password")
         .loginPage("/login")
         .permitAll()
         .and()
         .rememberMe()
         .rememberMeParameter("remember")
         .and()
         .httpBasic().disable()
         .logout().permitAll();

      }
   }
}

Upvotes: 1

Related Questions