Spring @WebMvcTest fails with @PreAuthorize controller classes generated by openapi-generator-maven-plugin

137 views Asked by At

I'm using the org.openapitools:openapi-generator-maven-plugin:7.0.1 to generate the controllers and request/response objects in a Spring Boot 3 project. This basically works fine but I have a problem with the security conifguration.

I'm overriding the *Delegate class generated by the plugin like this:

@RestController
public class PingController implements PingApiDelegate {

    @Override
    @PreAuthorize("hasRole('ping')")
    public ResponseEntity<String> ping() {
        return ResponseEntity.status(HttpStatus.OK).body("pong");
    }
}

As you can see in the following configuration class, all requests are authenticated by default and @EnableMethodSecurity is set to use the @PreAuthorize annotation.

RestSecurityConfiguration

@Configuration
@EnableMethodSecurity
@RequiredArgsConstructor
public class RestSecurityConfiguration {

    private final JwtAuthConverter jwtAuthConverter;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        return httpSecurity
                .csrf(AbstractHttpConfigurer::disable)
                .authorizeHttpRequests(httpRequests -> httpRequests.anyRequest().authenticated())
                .oauth2ResourceServer(oauth2ResourceServerCustomizer -> oauth2ResourceServerCustomizer.jwt(jwtCustomizer -> jwtCustomizer.jwtAuthenticationConverter(jwtAuthConverter)))
                .sessionManagement(sessionManagementCustomizer -> sessionManagementCustomizer.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .build();
    }
}

When testing the controller with a @WebMvcTest, then I get a HTTP 401 instead of 403 when the passed role does not match. The same test passes if I made the following changes:

  • Remove @EnableMethodSecurity and @PreAuthorize
  • Adding httpRequests.requestMatchers("/api/ping").hasRole("ping")

@WebMvcTest(PingController.class)
@Import({PingApiController.class})
class PingControllerTest extends AbstractControllerTest {

    @Test
    void should_return_pong() throws Exception {
        mockMvc.perform(get("/api/ping")
                        .with(authentication(defaultAuthentication("wrong-role"))))
                .andExpect(status().isForbidden());
    }

    protected static Authentication defaultAuthentication(String... authorities) {
        Jwt jwt = Jwt.withTokenValue("token")
                .header("alg", "none")
                .claim("email", "[email protected]")
                .build();
        final List<String> rolePrefixedAuthorities = Arrays.stream(authorities).map(authority -> "ROLE_" + authority).toList();
        return new JwtAuthenticationToken(jwt, AuthorityUtils.createAuthorityList(rolePrefixedAuthorities));
    }
}
0

There are 0 answers