spring-security: WebMvcTest / MockMvc bug with mocked Authentication ?
Summary
Injected Authentication
as @Controller
method parameter is null in a @WebMvcTest
when using a (Mockito) mocked authentication.
I tried with both an annotation and a request post processor.
Note that I have not the same problem in @WebFluxTest
, using the same annotation or a WebTestClient Configurer with implementation very similar to above mentioned post-processor.
Actual / Expected Behavior
The mocked authentication from the TestSecurityContext is not injected when it should
Version
Versions pulled by boot 2.2.6.Release (same issue at least with 2.2.4 and 2.2.5)
Sample
You can clone https://github.com/ch4mpy/spring-addons which contains
- the code for the
@WithMockAuthentication
annotation and its security context factory - the code for the
MockAuthenticationRequestPostProcessor
MockMvc request post-processor - sample of failing
@WebMvcTest
using both@WithMockAuthentication
andMockAuthenticationRequestPostProcessor
- sample of passing
@WebFluxTest
using@WithMockAuthentication
- sample of passing
@WebFluxTest
usingMockAuthenticationWebTestClientConfigurer
What I’d like to use:
@Test
@WithMockAuthentication(
authType = OidcIdAuthenticationToken.class,
name = "Ch4mpy",
authorities = "ROLE_AUTHORIZED_PERSONNEL")
public void greetCh4mpyWithAnnotation() throws Exception {
api.get("/greet")
.andExpect(content().string("Hello Ch4mpy! You are granted with [ROLE_AUTHORIZED_PERSONNEL]."));
}
@Test
public void greetCh4mpyWithRequestPostProcessor() throws Exception {
api.with(
mockAuthentication(OidcIdAuthenticationToken.class).name("Ch4mpy")
.authorities("ROLE_AUTHORIZED_PERSONNEL"))
.get("/greet")
.andExpect(content().string("Hello Ch4mpy! You are granted with [ROLE_AUTHORIZED_PERSONNEL]."));
}
Whith a controller like:
@RestController
public class GreetingController {
private final MessageService<OidcIdAuthenticationToken> messageService;
@Autowired
public GreetingController(MessageService<OidcIdAuthenticationToken> messageService) {
this.messageService = messageService;
}
@GetMapping("/greet")
public String greet(OidcIdAuthenticationToken auth) {
return messageService.greet(auth);
}
}
About this issue
- Original URL
- State: closed
- Created 4 years ago
- Comments: 20 (20 by maintainers)
Original reason why only some tests need to do advanced configuration on the mock.
In “real world”, I’d wrap authentication extraction:
and client code would be like
P.S. Please note I’m not requesting mocked authentication in spring-framework. I have it in a lib of mine I publish on maven-central and as so can use in any project I want since you explained me how to work around a Spring framework “expectation” about
getPrincipal()
having to be non nul forAuthentication
to be resolved as controller method argument.I find it useful enough to maintain it, I’d understand you don’t.