Reputation: 71
I'm having troubles testing a Spring WebFlux controller secured by Spring Security's @Secured
annotation. Here is my controller code :
@RestController
@RequestMapping("/endpoint")
public class MyController {
@GetMapping()
@Secured("ADMIN")
public Flux<MyOutputDto> getOutputDtos() {
return myService.getOutputDtos();
}
}
And here is my test code :
@WebFluxTest(MyController.class)
class MyControllerTest {
@Autowired
WebTestClient webTestClient;
@Test
@WithApplicationUser(roles = "ADMIN")
void should_work_fine() {
webTestClient.get()
.uri("/endpoint")
.exchange()
.expectStatus().isOk();
}
@Test
void should_return_401_unauthorized() {
webTestClient.get()
.uri("/endpoint")
.exchange()
.expectStatus().isUnauthorized();
}
@Test
@WithApplicationUser
void should_return_403_forbidden() {
webTestClient.get()
.uri("/endpoint")
.exchange()
.expectStatus().isForbidden();
}
}
The @WithApplicationUser
annotation is a custom annotation that injects a mock authentication object in the security context with provided roles. If no roles are provided (like in the third test) then it defaults to no role at all.
The problem here is that the first 2 tests work fine, but the third fails by returning 200 OK instead of 403 Forbidden. My first thought went for Spring Security not processing @Secured
annotation, so I followed many Spring WebFlux/Spring Security documentation and online articles, but none worked.
Does someone have an idea for this ? Thanks in advance
Upvotes: 3
Views: 7537
Reputation: 71
Okay so I figured out what was going on.
First, the @Secured
annotation seems to not be processed by Spring Security for reactive applications (i.e Spring WebFlux). With @EnableReactiveMethodSecurity
you must use @PreAuthorize
annotations.
Then, I had to create a test configuration and import it to my test and it worked like a charm.
@TestConfiguration
@EnableReactiveMethodSecurity
public class WebFluxControllerSecurityTestConfig {
}
@WebFluxTest(MyController.class)
@Import(WebFluxControllerSecurityTestConfig.class)
class MyControllerTest {
// Same tests
}
Upvotes: 4