Spring Security 5 and WebClient, Reactive or Servlet?

Bing Qiao
3 min readAug 16, 2020

--

One typical use case of OAuth2 via Spring Security 5 and WebClient has been implemented in this repo spring-webflux-security-demo in GitHub for both Spring Reactive and Servlet stacks.

A Spring Boot service using Spring Security OAuth2 (deprecated) has the following features:

  • Acting as a resource server protected by JWT Bearer token issued by authorization server A
  • Holding a client_credentials OAuth2RestTemplate to access external resource servers protected by JWT Bearer token issued by authorization server B
  • Extension to DefaultAccessTokenConverter to add custom authorities to authentication object
  • Method security to allow use of method access-control annotations such as PreAuthorize
  • Parsing Hypermedia responses

It wasn’t an easy path migrating this service to Spring Security 5. But after a lot of searching, experimenting, and frustrating, I now have two sets of projects that work for all above.

The mistake I made in the beginning was to mix Servlet and Reactive stacks in Spring. Spring WebClient can be used in both stacks but which stack to use has implications on what to configure and how to configure your Spring Beans.

What needs to be implemented is as shown below:

Client to Resource Server A to Resource Server B

The focus of this migration is to use WebClient instead of OAuth2RestTemplate which is deprecated in Spring Security 5.

The two servlet projects are as follows:

The two reactive projects are as follows:

To run those projects you will need a pair of clientId and clientSecret registered in an authorization server. I used a free Okta developer account to setup two authorization servers for testing.

Implementing above features in react or servlet stacks requires different setups for Dependencies, Security Configuration, Method Security and WebClient.

Reactive stack (netty in use)

  • Dependencies: exclude spring-boot-starter-tomcat from spring-boot-starter-web
  • Security Configuration: 1) apply @EnableWebFluxSecurity; 2) configure @Bean SecurityWebFilterChain that takes ServerHttpSecurity
  • Method Security: apply @EnableReactiveMethodSecurity
  • WebClient: 1) configure @Bean WebClient; 2) configurate @Bean ReactiveOAuth2AuthorizedClientManager that uses injected ReactiveClientRegistrationRepository and ReactiveOAuth2AuthorizedClientService

Servlet stack (tomcat in use)

  • Dependencies: spring-boot-starter-tomcat should not be excluded
  • Security Configuration: 1) apply @Configuration; 2) @Override WebSecurityConfigurerAdapter.configure
  • Method Security: apply @EnableGlobalMethodSecurity
  • WebClient: 1) configure @Bean WebClient; 2) configure @Bean ReactiveOAuth2AuthorizedClientManager that instantiates InMemoryReactiveClientRegistrationRepository and InMemoryReactiveOAuth2AuthorizedClientService

Resource server (netty or tomcat)

This project only implements Resource Server protected by JWT. The following is the how JWT issuer can be configured in application.yml.

Resource server and webclient (netty or tomcat)

This project implements Resource Server, client_credentials WebClient, Method Security, custom JwtGrantedAuthoritiesConverter and JwtBearerTokenAuthenticationConverter.

The following is how both site authentication (as Resource Server) and OAuth2 client can be configured in application.yml.

Errors if WebClient not configured properly when tomcat in use

  • required a bean of type ‘org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository’ that could not be found.
  • required a bean of type ‘org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService’ that could not be found.
  • The bean ‘clientRegistrationRepository’, defined in class path resource [org/springframework/boot/autoconfigure/security/oauth2/client/servlet/OAuth2ClientRegistrationRepositoryConfiguration.class], could not be registered. A bean with that name has already been defined in class path resource… and overriding is disabled.

--

--