62

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.

Community
  • 1
  • 1
rq_
  • 789
  • 1
  • 6
  • 6
  • 1
    Please show the actual requests/responses and/or provide a demo page. Right now, there are not enough details and it seems impossible to tell where things go wrong. – nmaier Jul 01 '14 at 20:04
  • Can you confirm that OPTIONS return code 200? – kojo Jul 02 '14 at 10:44
  • 6
    I resolved this issue. It seems that Firefox expects the list in Access-Control-Allow-Methods to be comma delimited. I changed it to "POST, GET, OPTIONS" and it magically started working. I figured this out by carefully reading https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS – rq_ Jul 02 '14 at 20:28
  • mines is comma delimited but it still does not work – shorif2000 Dec 04 '19 at 14:08
  • 8
    In case it might help others: For me it turned out to be a certificate issue. Chrome automatically uses certificates added to Windows. FireFox does not. So had to import our self-signed dev server certificate into FireFox, and then the CORS worked again. – Svish Aug 12 '20 at 08:07
  • 1
    I think @Svish's comment should be an answer – derekbaker783 Jul 16 '21 at 14:34

6 Answers6

80

QUESTION: "Why is this CORS request failing only in Firefox?"


ANSWER: While unrelated to the OP's specific case, it may help you to know that Firefox does not trust CA's (certificate authorities) in the Windows Certificate Store by default, and this can result in failing CORS requests in Firefox (as was alluded to by Svish in the question comments).


To allow Firefox to trust CA's in the Windows Certificate Store:

  • In Firefox, type about:config in the address bar
  • If prompted, accept any warnings
  • Right-click to create a new boolean value, and enter security.enterprise_roots.enabled as the Name Set the value to true
  • Then re-test the failing request

Answer source: https://support.umbrella.com/hc/en-us/articles/115000669728-Configuring-Firefox-to-use-the-Windows-Certificate-Store

derekbaker783
  • 8,109
  • 4
  • 36
  • 50
21

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.

Anne
  • 7,070
  • 1
  • 26
  • 27
2

Disabling HTTPS-Only Mode in Firefox solved the issue for me. I was trying to access a remote resource using HTTP from http://localhost.

shalometz
  • 69
  • 1
  • 4
2

Since Firefox 87 (released in March 2021), it's possible to set the below preference in about:config, namely the Firefox Configuration Editor:

network.cors_preflight.allow_client_cert: true

From Firefox for Enterprise 87 - Release notes:

Corporations that use TLS client certificates can flip the network.cors_preflight.allow_client_cert preference to get Google Chrome-compatible handling of the CORS protocol. In particular, contrary to the Fetch Standard, this will transmit TLS client certificates along with a CORS preflight. See bug 1511151 for more information.

References:

ryenus
  • 15,711
  • 5
  • 56
  • 63
0

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

var xmlhttp = new XMLHttpRequest();
xmlhttp.withCredentials = true;

xmlhttp.onreadystatechange = function () {
    if (xmlhttp.readyState == XMLHttpRequest.DONE) {
        if (xmlhttp.status == 200) {
            success_callback(xmlhttp.responseText);
        } else {
            error_callback(xmlhttp.statusText);
        }
    }
};
xmlhttp.open("DELETE", url);
xmlhttp.send(null);

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

#handle CORS requests by adding required headers
if ($http_origin ~* .example.com) {
    set $cors "CORS-${request_method}";
}

if ($cors = "CORS-OPTIONS") {
    add_header 'Access-Control-Allow-Credentials' 'true';
    add_header 'Access-Control-Allow-Headers' 'Content-Type';
    add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, DELETE';
    add_header 'Access-Control-Allow-Origin' $http_origin;
}

Good read on CORS: https://www.html5rocks.com/en/tutorials/cors/

Akshay Goyal
  • 941
  • 9
  • 11
0

Ubuntu users have 2 steps to fix it:

1- This solution

2- Enter this command in Terminal:

sudo cat <<EOF | sudo tee /usr/lib/firefox/distribution/policies.json
{
    "policies": {
        "Certificates": {
            "Install": [
                "/usr/local/share/ca-certificates/aspnet/https.crt"
            ]
        }
    }
}
EOF

Source: https://learn.microsoft.com/en-us/aspnet/core/security/enforcing-ssl?view=aspnetcore-7.0&tabs=visual-studio%2Clinux-ubuntu

Reza Taba
  • 1,151
  • 11
  • 15