CORS – Cross Origin Resource Sharing – is awesome, as most current browsers support it. It allows browsers to break free from the built-in (and useful, but sometimes limiting) security restrictions when it comes to calling APIs on different origins. CORS enables client-side cross origin requests, and details can be found here for example. But then, just yesterday, we noticed that PUT and DELETE requests from client-side AJAX code just did not work on the latest Chrome. We digged deeper, opened the network viewer and found that the CORS pre-flight request, used by the browser to verify that it is actually allowed to call that API on a different host, is responded with a 403 Not Authorized response. Bugger. The client browsers will not issue the real request if the pre-flight request returns that the origin is not authorized. It turns out that Chrome implements CORS fine to some degree, but there is an issue with these pre-flight requests. For these requests, the client browser may sent the Access-Control-Request-Headers header, e.g.
A default CORS implementation on a server will decline such a request, unless you actively agree that the request that the client wishes to make can be sent with the customer X-MYHEADER header. The problem on Chrome is, that it sends this for the pre-flight request:
Access-Control-Request-Headers: origin, content-type, accept
Without having origin, content-type and accept explicitly white-listed on the server, the pre-flight request will now get a 403. The funny thing is, that these headers are standard and don’t belong here. The browser should not send this header at all in our case. Luckily, Vladimir Dzhuvinov which wrote the excellent CORS Filter for Java EE Web Apps noticed this, too, and provides an easy fix. You have to add these request header names to the CORS configuration and simply accept them, even though they should not be in these pre-flights requests technially. Here is the combined CORS configuration for Vladimir’s CORS filter for our API:
CORS com.thetransactioncompany.cors.CORSFilter cors.supportedMethods GET, POST, HEAD, PUT, DELETE, OPTIONS cors.supportedHeaders origin, content-type, accept
Also, here is the official bug report with regard to CORS pre-flight requests for Google Chrome. Happy CORSing!