# 2. Who resolves the `CorsConfigurationSource` *Prev: [1. Two layers, one word](01-two-layers.md) · Next: [3. The three identical 403s](03-three-identical-403s.md)* There are two lookups involved in getting a CORS configuration into the filter chain, and they disagree about what they are looking for. One searches by **type**. The other searches by **name**. ## Lookup 1: should the CORS configurer run at all? `HttpSecurityConfiguration.applyCorsIfAvailable(HttpSecurity)`, disassembled from `spring-security-config` 7.1.1: ``` 4: ldc // class org/springframework/web/cors/UrlBasedCorsConfigurationSource 6: invokeinterface // ApplicationContext.getBeanNamesForType:(Ljava/lang/Class;)[Ljava/lang/String; 11: arraylength 12: ifle 23 19: invokevirtual // HttpSecurity.cors:(Customizer)HttpSecurity 23: return ``` By type, and the test is `ifle` — "branch if less than or equal to zero". One bean is enough. So is five. > The reference documentation says: *"If you have more than one `CorsConfigurationSource` bean, > Spring Security won't automatically configure CORS support for you, because it cannot decide > which one to use."* That is not what 7.1.1 does. > [`docs/output/06-two-sources.txt`](output/06-two-sources.txt) has two such beans, CORS > configured, and one of them serving traffic. ## Lookup 2: which source does the configurer use? `CorsConfigurer.getCorsConfigurationSource(ApplicationContext)`: ``` 7: ldc // String corsConfigurationSource 9: invokeinterface // ApplicationContext.containsBeanDefinition:(Ljava/lang/String;)Z 20: ldc // String corsConfigurationSource 24: invokeinterface // ApplicationContext.getBean:(String,Class)Object 34: invokestatic // MvcCorsFilter.getMvcCorsConfigurationSource:(ApplicationContext)CorsConfigurationSource ``` By name. The literal string `corsConfigurationSource`. If no bean definition carries that name, it falls through to Spring MVC's registrations. (There is a similar name check first, for a `CorsFilter` bean named `corsFilter`.) ## The gap between them Name a `UrlBasedCorsConfigurationSource` bean anything other than `corsConfigurationSource` and you land between the two lookups: CORS is switched **on** by the type lookup, and the configuration you wrote is **ignored** by the name lookup. That is the `misnamed` profile, and it produces the worst diagnostic in this whole subject: ``` HTTP/1.1 200 X-Content-Type-Options: nosniff X-XSS-Protection: 0 ... ``` Two hundred. No `Access-Control-Allow-Origin`. The browser blocks the request and reports a CORS error; your access log shows a successful `OPTIONS`; nothing anywhere is red. Why 200 rather than the 401 from chapter 1? Because `CorsFilter` is now in the chain, and its `if (!isValid || isPreFlightRequest(request)) return;` fires on the second clause. The request never reaches `AuthorizationFilter`. The only trace is one DEBUG line: ``` o.s.web.cors.DefaultCorsProcessor : Skip: no CORS configuration has been provided ``` Full transcript: [`docs/output/05-misnamed-bean.txt`](output/05-misnamed-bean.txt). ## What is in the context that you did not put there `/diag/cors-sources` on a stock Boot web application: ```json { "corsConfigurationSourceBeans": { "mvcHandlerMappingIntrospector": "HandlerMappingIntrospector" } } ``` `HandlerMappingIntrospector` implements `CorsConfigurationSource`. It is always there, it is not a `UrlBasedCorsConfigurationSource`, and it is the object the MVC fallback returns. That is why the fallback path never throws in a normal application — and why the failure is silent rather than loud. ## Rules that follow - Name the bean `corsConfigurationSource`. Exactly that. - If you want several, pass them per chain with `.cors(c -> c.configurationSource(..))`, which bypasses both lookups. - `NoSuchBeanDefinitionException: Failed to find a bean that implements \`CorsConfigurationSource\`` names three fixes and does not mention the fourth one, which is usually the right one: rename your bean. --- *Prev: [1. Two layers, one word](01-two-layers.md) · Next: [3. The three identical 403s](03-three-identical-403s.md)*