Thanks for raising a Spring Boot issue. What sort of issue are you raising? Bug report
Spring boot version: 1.5.8
General issue description: When a request is send from chrome using XMLHttpRequest, an origin header is added, which causes spring to report invalid CORS request, even though it's not actually a CORS request. See this SO question: https://stackoverflow.com/questions/15512331/chrome-adding-origin-header-to-same-origin-request
Adding the CrossOrigin annotation to the controller doesn't help. You have to add something like this to your WebSecurity configuration:
@Bean
fun corsConfigurationSource(): CorsConfigurationSource {
val source = UrlBasedCorsConfigurationSource()
val conf = CorsConfiguration()
conf.addAllowedHeader("*")
conf.addAllowedMethod("*")
conf.addAllowedOrigin("*")
source.registerCorsConfiguration("/**", conf)
return source
}
In my opinion Spring shouldn't give a 403, just because an origin header is present, chrome adds it to all POST requests, not just the Preflight Request.
Comment From: wilkinsona
Spring Framework's DefaultCorsProcessor will skip a request from the same origin. However, it's not clear from what you've described above if that code is definitely involved. Can you please provide a sample that reproduces the behaviour that you have described?
Comment From: spring-projects-issues
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Comment From: spring-projects-issues
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.
Comment From: skitching-um
Perhaps related to https://jira.spring.io/browse/SPR-16262? The original post does not mention whether a proxy was used in front of the app, but does describe setting addAllowedOrigin("*") which would "work around" the issue (by effectively disabling CORS checks completely).
Comment From: zlepper
That is indeed the case, we have traefik in front as a proxy.
Comment From: skitching-um
Ah, and traefik is also a proxy which fails to add X-Forwarded-Port: https://github.com/containous/traefik/issues/1220 So this is indeed the same issue as SPR-16262.
Comment From: zlepper
If I may be so currious as to ask: Why does spring even care about CORS, other than to tell the browser that it's alright to make the cors request? Isn't CORS only something the browser themselves really should care about?
Comment From: wilkinsona
@zlepper No, CORS is a serverside concern too. If you have questions about CORS, please ask on Stack Overflow.
Comment From: victortwc
No, CORS is NOT a server side concern. It is a browser requirement to circumvent the Same Origin Policy. Browsers should be the ones protecting the users from hideous requests, not the server. Adding serverside validation to origins and headers increases complexity and confusion (just search for "invalid cors request spring" and you will see how many unfortunate people are bitten by this from time to time).
It adds no extra server security whatsoever.
Comment From: petterdaae
Hi @wilkinsona, I think what @zlepper is trying to say is that spring should not reject cross origin requests, because it is the browser that should determine if a request should be blocked. It is indeed a server side concern too, but as far as I can see, the server should not block a request simply because it contains the Origin header. The fetch standard explicitly says that:
A CORS request is an HTTP request that includes an
[Origin](https://fetch.spec.whatwg.org/#http-origin)header. It cannot be reliably identified as participating in the CORS protocol as the[Origin](https://fetch.spec.whatwg.org/#http-origin)header is also included for all requests whose method is neitherGETnorHEAD.
Or am missing something?
I will gladly create a new issue with a minimal example if you think that any of this makes sense!
Comment From: wilkinsona
I believe you are missing something. From the Fetch standard:
A successful HTTP response, i.e., one where the server developer intends to share it, to a CORS request can use any status, as long as it includes the headers stated above with values matching up with the request.
A successful HTTP response to a CORS-preflight request is similar, except it is restricted to an ok status, e.g., 200 or 204.
Any other kind of HTTP response is not successful and will either end up not being shared or fail the CORS-preflight request. Be aware that any work the server performs might nonetheless leak through side channels, such as timing. If server developers wish to denote this explicitly, the 403 status can be used, coupled with omitting the relevant headers.
When a developer does not intend for a resource to be shared across origins, the spec states that "the HTTP response is not successful" and that "the 403 status can be used". This is exactly what Spring Framework does and what many other server side web frameworks also do.
Comment From: petterdaae
Thank you for your replying so quickly! 🤩
I totally agree. However, the reason I am confused with this is that the requests that are blocked are same-origin requests, not cross-origin requests. To my understanding, they are classified as cross-origin requests because they have the Origin header, and the fetch standard states that
It cannot be reliably identified as participating in the CORS protocol as the
[Origin](https://fetch.spec.whatwg.org/#http-origin)header is also included for all requests whose method is neitherGETnorHEAD.
or am I reading it wrong? 😅
Another thing that confuses me is that this is not a problem if you do not have CORS enabled in Spring. Spring projects without CORS accept requests regardless of what the Origin header is.
Comment From: wilkinsona
I totally agree. However, the reason I am confused with this is that the requests that are blocked are same-origin requests, not cross-origin requests.
It's impossible for us say what that's happening as we know nothing about your app, how it's deployed, and the requests that are being sent to it.
they are classified as cross-origin requests because they have the
Originheader
That should not be the case. To be classified as a CORS request, the request must have an Origin header with a host, scheme, or port that does not match the request's host, scheme, or port. This is implemented in org.springframework.web.cors.CorsUtils.isCorsRequest(HttpServletRequest). Note that this code is part of Spring Framework yet this is Spring Boot's issue tracker.
I would recommend following up with a question on Stack Overflow that fully describes your application, how it's deployed, the requests that are being sent to it, and the responses that are being received. Ideally, it would also include a minimal, reproducible example.
Comment From: petterdaae
Yes, sorry about that, I will create a new issue in Spring Framework with some more details! I can see that I did not fully understand how the request was classified as a CORS request, and it explains why we have this problem where our app is deployed as we use the host-header for routing.