Corentin
Corentin

Reputation: 71

How to test Spring Boot @WebFluxTest with Spring Security @Secured annotation

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

Answers (1)

Corentin
Corentin

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

Related Questions