My application has property spring.security.oauth2.resourceserver.jwt.issuer-uri= ${ISSUER_URI}
Empty WebMvcTest fails with
OAuth2ResourceServerJwtConfiguration$JwtDecoderConfiguration.jwtDecoderByIssuerUri ... Could not resolve placeholder 'ISSUER_URI' in value "${ISSUER_URI}"
WebMvcTest by default runs default security setup which requires authentication and plenty of annotations like WithMockedUser to authenticate request. It is handy as long as security configuration is textbook example of Spring Security Reference. I'm afraid it means rarely
Anyway, the concept is that authentication is realized by @With...
family and authorization is default - everything must be authenticated
Therefore, as OAuth2ResourceServerAutoConfiguration is responsible for authentication, it should not be activated by default.
Comment From: wilkinsona
It was intentionally added as part of https://github.com/spring-projects/spring-boot/issues/19823.
There are several security-related auto-configurations included in @WebMvcTest
through `@AutoConfigureMockMvc:
https://github.com/spring-projects/spring-boot/blob/89c7a681c0a6e3a2c664468c4e2de2d31671ea77/spring-boot-project/spring-boot-test-autoconfigure/src/main/resources/META-INF/spring/org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc.imports#L5-L11
They're included so that Security configuration and Security-related features can be used and tested using @WebMvcTest
. We certainly wouldn't remove all of them and I'm not convinced that OAuth2ResourceServerAutoConfiguration
deserves special treatment. Can you please elaborate on why you think that it does?
Comment From: michaldo
Controllers and security are separated. Security responsibility is pass or reject request, controller responsibility is - in short - parse request and pass to service.
WebMvcTest purpose is testing controllers.
However, there is a tunnel between security and controller. Security pass - in short - @AuthenticationPrincipal to controller.
Controller method void get(@AuthenticationPrincipal Jwt jwt)
must be testable with WebMvcTest.
To achieve it, WebMvcTest activates some security configuration and exposes - in short - few SecurityMockMvcRequestPostProcessors.* methods, which allows "push" AuthenticationPrincipal to the tunnel.
The tunnel for Jwt works well without OAuth2ResourceServerAutoConfiguration. It is enough to write
mockMvc.perform(get("/").with(jwt()))
What was the issue with https://github.com/spring-projects/spring-boot/issues/19823? @RegisteredOAuth2AuthorizedClient
.
@AuthenticationPrincipal is resolved by AuthenticationPrincipalArgumentResolver, which is activated unconditionally, @RegisteredOAuth2AuthorizedClient
is resolved by OAuth2AuthorizedClientArgumentResolver , which is activated only if OAuth2AuthorizedClientManager exists (org.springframework.security.config.annotation.web.configuration.OAuth2ClientConfiguration.OAuth2ClientWebMvcSecurityConfiguration#addArgumentResolvers)
Is issue 19823 solved? No. Autoconfiguration does not cause OAuth2AuthorizedClientArgumentResolver is registered. Some other beans are required to activate the resolver.
In fact, issue 19823 is: "Hi, my WebMvcTest does not work because OAuth2AuthorizedClientArgumentResolver is absent. I have couple of beans in my application which finally activates OAuth2AuthorizedClientArgumentResolver, if only autoconfiguration is present. Could you please bloat WebMvcTest with extra autoconfiguration to register OAuth2AuthorizedClientArgumentResolver? I would really appreciate it. " And answer is: "My pleasure. It will be bloated even more, with OAuth2ResourceServerAutoConfiguration.".
But, If you accept my proposal and remove OAuth2ResourceServerAutoConfiguration from WebMvcTest, many people will complain: My tests does not work anymore. I took WebMvcTest, - something reducing context to minumum required by controller needs-, I added a security based on JWT and now I have to manually add OAuth2ResourceServerAutoConfiguration. They are not surprised that DataSource needs DataSourceAutoConfiguration, but they used to JWT does not need OAuth2ResourceServerAutoConfiguration.
Why?
Maybe because current WebMvcTest default authorization - request is authenticated - may not apply to real applications. They are forced to use WebMvcTest with real authorization, which depends on autoconfiguration.
How to fix it?
It should be clearly stated, that WebMvcTest is for controllers needs. To support @RegisteredOAuth2AuthorizedClient, @AuthenticationPrincipal, etc
1. All possible argument resolvers, like OAuth2AuthorizedClientArgumentResolver, should be registered by default.
2. Default authorization should permitAll
, to not force anybody use real authorization.
Basically, WebMvcTest should focus on controller only and open tunnel for all possible @AuthenticationPrincipal, etc.
And, it should be clearly stated, how real, application authorization should be tested with isolation from real controllers. Similar to WebMvcTest, with all security autoconfigurations, with dummy controller behind, with examples how to mock infrastructure like ISSUER_URI
Comment From: wilkinsona
Could you please bloat WebMvcTest with extra autoconfiguration to register OAuth2AuthorizedClientArgumentResolver? I would really appreciate it
My pleasure. It will be bloated even more, with OAuth2ResourceServerAutoConfiguration
This sarcasm is insulting to those involved and is unnecessary. Please read the code of conduct and comment respectfully and constructively in future.
Default authorization should permitAll, to not force anybody use real authorization. Basically, WebMvcTest should focus on controller only
That is not the intended purpose of @WebMvcTest
. As described in its javadoc, it deliberately includes Spring Security so that a controller's security can be tested. Including OAuth2ResourceServerAutoConfiguration and the various other Security-related auto-configuration is aligned with this and isn't something that we want to change. Thanks anyway for the suggestion.