This is a demo project to show how to bypass the OAuth 2.0 Client Credentials Flow in a Spring Boot Integration Test. This is useful for projects using the Spring WebClient to interact with OAuth-2.0-secured resources in a machine-to-machine scenario with no user interaction.
Clone this repository and checkout either
- branch reactive-stack for a completely Reactive Spring WebFlux based demo or
- branch servlet-stack for a Servlet-Stack based or mixed-Stack based (meaning Servlet-Stack and Reactive WebFlux) demo
Then run mvn test -Dtest=TheRestClientImplIT
to see an integration test of
the TheRestClientImpl
using
the Spring WebClient
to fetch a secured resource using a stubbed Authorization Token:
2021-04-09 21:24:59.886 INFO 28221 --- [erver-EventLog0] org.mockserver.log.MockServerEventLog : 62997 received request:
{
"method" : "GET",
"path" : "/api/v1/some-resource",
"headers" : {
"accept-encoding" : [ "gzip" ],
"user-agent" : [ "ReactorNetty/1.0.5" ],
"host" : [ "127.0.0.1:62997" ],
"accept" : [ "*/*" ],
"Authorization" : [ "Bearer c29tZS10b2tlbg==" ],
"content-length" : [ "0" ]
},
"keepAlive" : true,
"secure" : false
}
The project is a Spring Boot project configured for OAuth 2.0 Client functionality with Spring Security - see WebClientOAuth2Configuration and application.yml.
This configures any Spring WebClient in the application provided by the autoconfigured WebClient.Builder to transparently perform an OAuth 2.0 Client Credentials Flow on every REST-Resource request, using an OAuth2AuthorizedClientManager or a ReactiveOAuth2AuthorizedClientManager (depending on the selected Web Stack).
So, to bypass this Flow in an integration test we can provide a mock implementation @Bean
of the
configured xxOAuth2AuthorizedClientManager
in the TestContext
. This mock implementation is located
in AlwaysAuthorizedOAuth2AuthorizedClientManager
(notice the @Primary
and @TestComponent
annotations) and is @Import
ed in the integration test
class TheRestClientImplIT
. It simply returns a new instance of
an OAuth2AuthorizedClient
(or a Mono of that on Reactive
Stack)
stubbed with a valid OAuth 2.0 Client Credentials Authorization and Token, thus no Authorization request is ever needed
for any REST-Resource request.
The other classes in this project under src/test/java
are just helper classes for configuring
the MockServer for the REST-Resource request (the one the integration test is normally
interested in). Also, we can monitor its logs to see that the stubbed Authorization Token is really used for the
request. While I find this one convenient, you may of course use any mock server you like in your project ;)
- Spring Boot WebClient Customization
- Spring Boot OAuth 2.0 Autoconfiguration
- Spring Security OAuth 2.0 WebClient configuration (Servlet Stack)
- Spring Security OAuth 2.0 WebClient configuration (Reactive Stack)
- Spring Security Testing OAuth 2.0 Clients
(This gave me the crucial hint for my solution to just stub an
OAuth2AuthorizedClient
from the mockxxOAuth2AuthorizedClientManager
) - Baeldung - WebClient Client Credentials Flow
(Beware that this write-up uses the now deprecated
UnAuthenticatedServerOAuth2AuthorizedClientRepository
, that is why I opted forReactiveOAuth2AuthorizedClientManager
in my solution)