Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

XmlHttpRequest denied by Access-Control-Allow-Origin even though origin matches perfectly

Vitals:

Chrome Version 23.0.1271.64 Mac OS X 10.8.2

The Situation:

I have a web service exposed at https://api.myapi.com/... I would like to allow JavaScript applications to interact with this API. CORS feels like the obvious best fit (jsonp and friends being terrible, terrible hacks).

I can see in my Developer Tools that preflight requests are being sent out:

Request URL: https://api.myapi.com/someapi
Request Method: OPTIONS
Status Code: 200 OK

Request Headers

Accept: */*
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Access-Control-Request-Headers: origin, authorization, accept
Access-Control-Request-Method: GET
Connection: keep-alive
Host: api.myapi.com
Origin: http://prototypes.mycompany.com
Referer: http://prototypes.mycompany.com/somepage.html
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11

Response Headers

Access-Control-Allow-Headers: Accept,Authorization,Content-Length,Content-Type,Cookie
Access-Control-Allow-Methods: GET,POST,PUT,DELETE,HEAD,OPTIONS
Access-Control-Allow-Origin: http://prototypes.mycompany.com
Access-Control-Allow-Credentials: true
Connection: close

This looks great, in particular the response Access-Control-Allow-Origin header seems to match the request Origin header precisely.

Immediately afterwards, the actual request is attempted:

Request URL: https://api.myapi.com/someapi

Request Headers

Accept: application/json, text/javascript, */*; q=0.01
Authorization: <custom authentication scheme, removed>
Origin: http://prototypes.mycompany.com
Referer: http://prototypes.mycompany.com/somepage.html
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_2) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11

It then shows up as "Cancelled" and the following error is emitted:

XMLHttpRequest cannot load https://api.myapi.com/someapi. Origin http://prototypes.mycompany.com is not allowed by Access-Control-Allow-Origin.

I originally started with * as my allowed origin, but that fails with precisely the same problem.

I have replicated this problem on Mobile Safari for iOS 5, and Firefox as well. In Firefox the behavior is even more confusing: The server responds 200 OK and then 6-7KB of data (which is what I expect). The client side log says that it got a 200 OK and ~300 bytes of data (with no response headers, no response at all...) and then triggers the "error" handler.

What am I missing?

like image 568
Steven Schlansker Avatar asked Nov 12 '22 16:11

Steven Schlansker


1 Answers

Problem solved! I had to break out gdb to figure it out though...

A proxy server was inserting its own CORS headers into the request. So the HTTP session had the headers specified multiple times. The security check was checking against the first header, which was "*", and fails the request. The request failure prints out the last header value, which looks correct.

Not very helpful, WebKit!

like image 76
Steven Schlansker Avatar answered Nov 15 '22 05:11

Steven Schlansker