59

I am making a CORS xhr request. This works fine in chrome, however when I run in safari I get an 'Can not load ---- access not allowed by Access-control-allow-origin'. The code is exactly the same and I have set the CORS on the server. Below is my code.(has access control, but you are free to try without the accessToken)

 var water;
 var req = new XMLHttpRequest;
 req.overrideMimeType("application/json");
 req.open('GET', 'https://storage.googleapis.com/fflog/135172watersupplies_json', true);
 req.setRequestHeader('Authorization', 'Bearer ' + accessToken);
 origThis = this;
 var target = this;
 req.onload = function() {
 water = req;

 req.send(null);

After looking at the request headers I see that a OPTIONS request is made first and this is the request that is not allowed. The origin header is not included in the response in Safari, but is in chrome. What would cause this. Any help would be greatly appreciated.

UPDATE: I have tried in Safari for Windows and it works, so I'm not sure what is going on here. The mac that I am using is a remote access (Macincloud.com), but I don't think that would have anything to do with it.

Patrick Jackson
  • 18,766
  • 22
  • 81
  • 141

13 Answers13

51

I encountered the same error when making an XHR request against a file in Amazon S3. On Safari 7 it was failing. I know you're not using Amazon S3, but I thought I'd post in case this solution helped others.

The problem was that Safari 7 set the Access-Control-Request-Headers header to "origin, x-requested-with", but my AWS CORS configuration only allowed "x-requested-with":

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
        <AllowedHeader>x-requested-with</AllowedHeader>
    </CORSRule>
</CORSConfiguration>

I added "origin" as an allowed header and everything worked fine.

        <AllowedHeader>origin</AllowedHeader>

Note: the AllowedOrigin of * is for development purposes only. See @andes comment below for more information.

Seth
  • 6,514
  • 5
  • 49
  • 58
  • 8
    If you're following this example, please note that using * for AllowedOrigin is really meant for dev environments - you should use a white list in production, for most use cases. Here's an example for implementing a whitelist: https://github.com/monsur/CORSinAction/blob/master/ch07/listing-7.1/app.js – andes Feb 11 '15 at 16:12
  • 1
    If still someone is having issues, what fixed mine was using `origin` (lowercase) because I had `Origin` – returnvoid Apr 23 '19 at 20:17
  • I cannot find evidence in https://bugs.webkit.org/ of Safari ever listing `Origin` in the `Access-Control-Request-Headers` header. – jub0bs Jul 23 '23 at 13:43
12

I just had a similar problem, CORS error. It would work in Firefox & Chrome but not Safari 10.

Turned out we needed to put the trailing slash on the JSON URL.

William Macdonald
  • 2,139
  • 2
  • 21
  • 27
  • 1
    What the heck? This worked for me too. Thanks but what's wrong with Safari? – Michael May 01 '19 at 10:15
  • 10
    What trailing slash on what JSON URL? The XHR request that is failing? Some Allowed-origin header? Please elaborate. – FooBar May 31 '20 at 12:13
  • Thank you! This worked for me. Without backslash, CORS error on Safari, fine in FF & Chrome. With backslash, fine on Safari, FF & Chrome! – spiraleddy Aug 26 '20 at 20:56
4

Im not sure if anyone else will have this problem but I was making a request to a URL like:

https://api.website.com/api/v1/users/auth0|5ef7502019360a7/

The | (pipe) character in the URL was causing a strange issue with Safari because it was not being URL Encoded correctly.

In my Javascript I simply replaced my old url:

const url = "https://api.website.com/api/v1/user/auth0|5ef27593603a7";

with

const url = "https://api.website.com/api/v1/user/auth0|5ef27593603a7".replace("|", "%7C");

%7C is the correct URL encoding for the | (pipe) character.

Hope this helps someone!

  • 2
    Provided correct CORS headers are generated by the web-server, this is the next thing to check. For me, everything was was working on Chrome, but I was getting a preflight error in Safari. A better approach would be to `encodeURI(url)` the whole url rather than manually replacing characters. Other than this has fixed it for me. – Valerio Mazzeo Dec 23 '21 at 16:26
3

Set two response headers:

  1. Access-Control-Allow-Methods: '*', allow all

  2. Turns out server had Access-Control-Allow-Methods response header's value is set to *. It had to explicitly set to allow methods instead of a wildcard as it is not supported by a safari in iOS as given here in this MDN doc.

https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Methods

code.rookie
  • 346
  • 2
  • 6
2

As for Amazon S3, it only worked in safari after I added more allowed headers, Content-Type and Range. One of these did the job.

<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
    <CORSRule>
        <AllowedOrigin>*</AllowedOrigin>
        <AllowedMethod>GET</AllowedMethod>
        <AllowedMethod>POST</AllowedMethod>
        <MaxAgeSeconds>3000</MaxAgeSeconds>
        <AllowedHeader>Authorization</AllowedHeader>
        <AllowedHeader>Origin</AllowedHeader>
        <AllowedHeader>X-Requested-With</AllowedHeader>
        <AllowedHeader>Content-Type</AllowedHeader>
        <AllowedHeader>Range</AllowedHeader>
    </CORSRule>
</CORSConfiguration>
Edhowler
  • 715
  • 8
  • 17
2

In my case, it was an issue for Accept-Language header. I have added Accept-Language inside Access-Control-Allow-Headers and it got resolved.

dominik
  • 5,745
  • 6
  • 34
  • 45
deen
  • 2,185
  • 7
  • 29
  • 53
1

I had the same problem where CORS worked in Chrome, but threw an origin error in Safari. Turned out it was a Kerberos authorization issue. When I loaded the XHR URL directly in Safari, I was prompted for credentials. After entering them, I returned to the original site, and Safari no longer had the CORS error.

Seth Moore
  • 106
  • 5
1

We had the exact same issue on Cloudfront (backed by s3 bucket) and the solutions given here did not help. The problem was with Cloudfront clipping some headers. This resolved it for us:

https://aws.amazon.com/premiumsupport/knowledge-center/no-access-control-allow-origin-error/

Putting it here just in case someone comes across this solution in future.

Sarang
  • 2,143
  • 24
  • 21
1

I had a similar problem. I had a site where the login worked from site A, upon a successful login, the user would get redirected to site B. Both site A and B load the same language file from site A. What was happening to me, was that the file got first loaded on site A (No CORS required) but when the user went to site B, Safari interpreted it had that file already, but the internal failed with a CORS error, as it had it cached from site A.

The solution is to make the server add a "Vary: Origin" header to the response so that dumb Safari knows how to properly manage the cached file.

hernvnc
  • 827
  • 11
  • 18
0

For CORS request you should be using your origin fflog.storage.googleapis.com. If you use common storage.googleapis.com origin, any site can access to your bucket.

have try try remove overrideMimeType? If you set mime type, it will return correctly.

I also have problem with Safari POST request, but no answer yet. GET is OK.

Kyaw Tun
  • 12,447
  • 10
  • 56
  • 83
0

When I try

curl -v -X OPTIONS \
  -H 'Origin: fflog.storage.googleapis.com' \
  -H 'Access-Control-Request-Method: GET'  \
  https://storage.googleapis.com/fflog/135172watersupplies_json

I get, among other headers:

Access-Control-Allow-Origin: *

When I execute AJAX requests against https://storage.googleapis.com/fflog/135172watersupplies_json from Safari 6.0.4 on Mac OS 10.8.3 I get 403 errors, but they do all execute.

So I can only guess that you are trying to send a credentialed request for which a wildcard Access-Control-Allow-Origin is not allowed.

Old Pro
  • 24,624
  • 7
  • 58
  • 106
-1

try to remove overide mimetype.

 var
 jsonhandler=function(){var req=JSON.parse(this.response);console.log(req)},
 req=new XMLHttpRequest;
 req.open('GET','https://storage.googleapis.com/fflog/135172watersupplies_json');
 req.setRequestHeader('Authorization','Bearer '+accessToken);
 req.onload=jsonhandler;
 req.send();
cocco
  • 16,442
  • 7
  • 62
  • 77
-5

Thanks for all the responses, I got this finally myself. I added 'Origin' to my responseHeaders and works fine now.

Patrick Jackson
  • 18,766
  • 22
  • 81
  • 141
  • 44
    Could you elaborate a bit about the response. – Sohaib Oct 07 '15 at 09:54
  • 4
    Which kind of header? and where to put it? can you please add the exact steps with code? – Umesh Patadiya Dec 21 '18 at 12:49
  • In PHP I believe he added something like this: `header( 'Access-Control-Allow-Headers: Accept, Accept-Encoding, Accept-Language, Authorization, Cache-Control, Pragma, Content-Type, Origin, Referer, Sec-Fetch-Dest, Sec-Fetch-Mode, Sec-Fetch-Site, User-Agent, X-Requested-With');` – FooBar May 31 '20 at 12:29