Describe the bug We are using OpenApi Generator to generate an Interface for our Controller. When I add @EnableMethodSecurity with @PreAuthorize I get the error: No static resource for that endpoint.

To Reproduce I've made a reproducable project: method-security-issue See src/main/java/nl/hlopez/methodsecurityissue/controller/MyController.java

Expected behavior I expect the test to pass when the controller is implementing the interface (see commented code):

@RestController
public class MyController { // implements MyControllerApi {

    private final Logger logger = LoggerFactory.getLogger(MyController.class);

    @PreAuthorize("hasRole('SUPERPOWER')")
    @PostMapping(path = "/v1/message", consumes = MediaType.TEXT_PLAIN_VALUE)
    public ResponseEntity<Void> postAMessage(@RequestBody String message){
        logger.info("Received message: {}", message);
        return ResponseEntity.status(HttpStatus.CREATED).build();
    }

//    @PreAuthorize("hasRole('SUPERPOWER')")
//    @Override
//    public ResponseEntity<Void> postAMessage(String message){
//        logger.info("Received message: {}", message);
//        return ResponseEntity.status(HttpStatus.CREATED).build();
//    }

}

The test is testing if the user has the correct role.

@Import(SecurityConfig.class)
@MockBean(classes = {JwtDecoder.class})
@WebMvcTest(controllers = {MyController.class})
@WithMockUser(username = "superman", roles = {"SUPERPOWER"})
class MyControllerMvcTest {

    @Autowired
    private MockMvc mockMvc;

    @Test
    void postAMessage() throws Exception {
        mockMvc.perform(
                        MockMvcRequestBuilders
                                .post("/v1/message")
                                .header(HttpHeaders.CONTENT_TYPE, MediaType.TEXT_PLAIN_VALUE)
                                .content("Hello from test!")
                )
                .andExpect(MockMvcResultMatchers.status().is2xxSuccessful());
    }

}

Without @EnableMethodSecurity it works (just by-passes the role check). Wen not implementing an interface it works with @EnableMethodSecurity, but as soon we implement an interface it breaks.

Sample Here the link to the GitHub repository with a minimal reproducible sample: method-security-issue

Comment From: sjohnr

Thanks for the report @hmmlopez! I'm not certain what would cause the 404 error without more investigation.

In the meantime, you can try setting proxyTargetClass = true on the @EnableMethodSecurity annotation. This appears to work around the issue by forcing the use of a CGLIB proxy instead of a JDK proxy. As mentioned in the Spring Framework docs under Proxying Mechanisms:

If the target object to be proxied implements at least one interface, a JDK dynamic proxy is used. [...] If the target object does not implement any interfaces, a CGLIB proxy is created.

This likely explains why the behavior changes as soon as you implement an interface.

Comment From: sjohnr

@hmmlopez regarding the 404, this comment explains the issue well. The Spring Framework docs contains a note stating:

Keep in mind that as of 6.0, with interface proxying, Spring MVC no longer detects controllers based solely on a type-level @RequestMapping annotation on the interface. Please, enable class based proxying, or otherwise the interface must also have an @Controller annotation.

In your case, you can either have:

@EnableMethodSecurity(proxyTargetClass = true)

or add @RestController to the interface generated by OpenAPI (if possible). Either of these solutions will allow the controller to be proxied and used with method security.

I'm going to close this as a duplicate of gh-9697. Thanks again for reaching out!

Comment From: hmmlopez

Thanks using proxyTargetClass = true works for me, going to check the other option of adding @RestController to the interface through openapi generator..

Comment From: hmmlopez

Unfortunatly the openapi generator does not add RestController but it does have the option to add @Controller so I'll stick to the proxyTargetClass.