Spring – Microservices and Spring Security OAuth2

oauth-2.0springspring-security

I already have a OAuth2 authorization server running in another project. Now I would need to secure several simple spring-boot rest-servers with OAuth2. But I'm finding the Spring documentation really really limited when it comes to separating Authorization and Resource servers.

I've also found several questions where the answer has been "Well they can be different boxes as long as they share the same tokenStore datasource". Can this really be true? How could this ever work for microservices? It would seem like a really odd thing that every rest service would need to implement it's own OAuth authorization server.

So how do I setup Oauth2.0 security for spring-boot rest-endpoints that refer to a remote oauth authorization server (possibly not even written with Spring)?

There's this thing called RemoteTokenServices that seems promising but it's not really documented at all.

Best Answer

While configuring your auh server::

Create a new clientDetails in ClientDetailsServiceConfigurer for resource server. which will be used to configure RemoteTokenService.

Configure Spring Security OAuth2 in your resource server:

Create a class which is annotate with @EnableWebSecurity ,@Configuration and extends WebSecurityConfigurerAdapter.

@Configuration
@EnableWebSecurity
protected static class ResourceConfiguration extends WebSecurityConfigurerAdapter {
  // methods        
}

Create a method with @Bean annotated which will return instance of TokenService, which will be used to create AuthenticationManager.

In this method create an instance of RemoteTokenService and set clientId, client_secret , checkTokenEndpointUrl and DefaultAccessTokenConverterWithClientRoles (this class is our implementation to get client_authority while authenticating accessToken in OAuth2 server.)

@Bean
public ResourceServerTokenServices tokenService() {
    RemoteTokenServices tokenServices = new RemoteTokenServices();
    tokenServices.setClientId("resource_id");
    tokenServices.setClientSecret("resource_secret");
    tokenServices.setCheckTokenEndpointUrl("http://<server-url>: <port>/oauth/check_token");
    return tokenServices;
}

Override authenticationManagerBean() method and annotate it with @Bean and return an instance of OAuth2AuthenticationManager with TokenService injected.

@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
    OAuth2AuthenticationManager authenticationManager = new OAuth2AuthenticationManager();
    authenticationManager.setTokenServices(tokenService());
    return authenticationManager;
}

Create a class annotated with @EnableResourceServer , @Configuration and extend ResourceServerConfigurerAdapter.

@Configuration
@EnableResourceServer
protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter {
  // Mehotds
}

Override Configure methods form the super class to configure resource server. Different configurer to configure Resource server.

ResourceServerSecurityConfigurer : to configure Resource_id.

HttpSecurity : This will configure security filter to tell it that user requires authentication for protected URLs (APIs).

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

@Override
public void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http
     .authorizeRequests()
     .antMatchers("/**").authenticated()
     .and()
     .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    // @formatter:on
}

.antMatcher("/**").authenticated() this line will secure every api url of your resource server. .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) will not create session.

PS:: If any thing is wrong then tell me.