Whilst looking at https://github.com/spring-projects/spring-boot/issues/23421 I noticed a few of our migrations use the @Order annotation on beans.

A common pattern would be:

@Bean
@Order(SecurityProperties.BASIC_AUTH_ORDER - 1)
SecurityFilterChain configure(HttpSecurity http) throws Exception {
    http.requestMatcher(new AntPathRequestMatcher(this.url)).authorizeRequests().anyRequest().anonymous().and()
            .csrf().disable();
    return http.build();
}

and

@Bean
@Order(SecurityProperties.IGNORED_ORDER)
IgnoredCloudFoundryPathsWebSecurityCustomizer ignoreCloudFoundryPathsWebSecurityCustomizer() {
    return (web) -> web.ignoring().requestMatchers(new AntPathRequestMatcher("/cloudfoundryapplication/**"));
}

I'm not convinced that these @Order annotations are working in these locations (or perhaps they're not supposed to be used that way).

Looking at the code, I think WebSecurityConfiguration.setWebSecurityCustomizers and WebSecurityConfiguration.setFilterChains are responsible for managing the beans and they sort items directly. I'm pretty sure that this doesn't consider any annotations on the @Bean method.

I think that using ObjectProvider.orderedStream() might be a better choice since it will wire up a FactoryAwareOrderSourceProvider OrderComparator.OrderSourceProvider

Comment From: eleftherias

@philwebb We had an existing test checking the order on SecurityFilterChain and I just added an additional one for WebSecurityCustomizer. As far as I can tell, the @Order annotation is working. Do you have an example configuration where they aren't being ordered correctly?

Comment From: philwebb

@eleftherias I'm afraid not, it was just an observation from looking at the code. I may well have got it wrong. Perhaps Spring is injecting the list already sorted and re-sorting it doesn't cause a side-effect. I'll close this one since the tests seem to prove it's working.

Comment From: mbhave

@eleftherias Here is an example where Spring Security's sort will flip the order that Spring Framework injected them in:

@Bean
@Order(1)
SecurityFilterChain securityFilterChain1(HttpSecurity http) throws Exception {
    //something
    return http.build();
}

@Bean
TestSecurityFilterChain securityFilterChain2(HttpSecurity http) throws Exception {
    return new TestSecurityFilterChain();
}

@Order(2)
static class TestSecurityFilterChain implements SecurityFilterChain {
    //implement methods
}

Spring Framework will inject securityFilterChain1, securityFilterChain2. Then Spring Security will sort them again using securityFilterChains.sort(AnnotationAwareOrderComparator.INSTANCE);. It sees @Order on TestSecurityFilterChain but nothing on securityFilterChain1 because it does not look at bean definitions. securityFilterChain2 will then end up before securityFilterChain1. I don't see a need for Spring Security to call securityFilterChains.sort(AnnotationAwareOrderComparator.INSTANCE); and it seems like it could be dropped.

Comment From: eleftherias

Thanks for the sample @mbhave. I'm reopening the issue.