I'm implementing CORS with credentials and a preflight request and I'm a bit mystified why the preflight request consistently fails in Firefox 30 but works in Safari (7.0.2) and Chrome 35. I think this issue is different from "Why does the preflight OPTIONS request of an authenticated CORS request work in Chrome but not Firefox?" because I am not getting a 401, but rather a CORS-specific message from the browser client:
"Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://myurl.dev.com. This can be fixed by moving the resource to the same domain or enabling CORS."
Without showing source code, here's what I'm doing:
On the server:
Headers for OPTIONS response:
- Access-Control-Allow-Origin: [[copy origin from the request here]]
- Access-Control-Allow-Methods: "POST GET OPTIONS"
- Access-Control-Allow-Headers: "X-Requested-With"
- Access-Control-Allow-Credentials: "true"
Headers for POST response:
- Access-Control-Allow-Origin: [[copy origin from the request here]]
- Access-Control-Allow-Credentials: "true"
In the browser client:
jQuery.ajax({
url: requestUrl,
type: 'POST',
data: getData(),
xhrFields: {
withCredentials: true
}
});
Per the spec, this will trigger a OPTIONS preflight request which needs to have the CORS headers in its response. I've read through the W3C spec several times and I can't identify what I'm doing wrong, if anything, in that preflight response.
I have noticed that when you a send CORS(Cross Origin Resource Sharing) request with cookies set, Firefox doesn't send the required response headers.
Solution:
Below solution adds headers only for OPTIONS requests and accepts requests only from example.com. You can change the implementation for other request methods and expected hosts.
JS CODE
When you send a DELETE request, the browser send a pre-flight request for OPTIONS, which expects Access-Control-Allow-Methods in the response headers. Based on this header value the actual DELETE request is sent. In Firefox, when you send a DELETE request the pre-flight request's response headers do not have expected headers, therefore it fails to send the actual DELETE request.
To overcome this problem use the below NGINX server config.
NGINX CODE
Good read on CORS: https://www.html5rocks.com/en/tutorials/cors/
Note that Firefox is the only browser that is compliant here. If parsing of
Access-Control-Allow-Methods
fails per https://fetch.spec.whatwg.org/#cors-preflight-fetch a network error needs to be returned. And per the ABNF for the header value it is most definitely a comma-separated value.