CORS preflight request returning "403 Forbidden"; subsequent request then only sending in Chrome
Solution 1
It's taken me a week, but I've finally found the problem.
By default, IIS6 does not support the OPTIONS verb on .php files (or .asp(x) for that matter).
As such, it wasn't recognising the OPTIONS
preflight call at all.
To change this value in IIS6, follow these steps:
- In the IIS Manager, go to your root web site directory. Right-click it and select "Properties"
- Go to the Home Directory tab, then select the "Configuration" button at the bottom
- Find the relevant file extension of the script you're trying to communicate with, such as .php or .asp and click "edit"
- Add
OPTIONS
to the list of available verbs (should now display something likeREQUEST, GET, POST, OPTIONS
) - Add the code below to your PHP script to determine responses from IE
I couldn't get Internet Explorer working without the following code in my PHP script:
/* Is the request from Internet Explorer? */
if( !isset( $_SERVER['HTTP_X_REQUESTED_WITH'] )
|| ( isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] != "XMLHttpRequest" ) ) {
/* If so, we need to send a UUID and iframe XSS response script... */
header("Content-Type: text/html");
/* This needs some extra security, for sure */
if( $result["success"] == "true" )
$result["uuid"] = $_POST["qquuid"];
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
echo "<script src='iframe.xss.response-3.4.1.js'></script>";
} else {
/* Otherwise, we can just echo the json'd result */
echo htmlspecialchars(json_encode($result), ENT_NOQUOTES);
}
I've given Ray Nicholus the 50 point bounty as although I didn't find his manner particularly helpful, he was right all along. However, for purposes of others viewing this post with a similar issue, I'll mark my answer as correct.
Solution 2
As mentioned in my comments, this appears to be an issue with your server. For some reason, it is rejecting the initial OPTIONS request. You will need to look at your server logs to see why your server is responding to this request with a 403.
The user agent sends this initial OPTIONS (pre-flight) request. Fine Uploader does not send this request directly, the user agent sends it to be in compliance with the CORS spec. If you have specific questions about CORS, you can see my blog post on how Fine Uploader handles CORS, or/and you can read this excellent MDN article on CORS.
turbonerd
Senior DevOps Engineer working with AWS, Kubernetes and CircleCI.
Updated on July 17, 2022Comments
-
turbonerd almost 2 years
After failure using pluploader in this question, I'm now trying FineUploader.
After reading up on CORS, I've implemented various headers on my IIS6 server.
What seems to happen is that my script fires the first (
preflight
) authorisation request, which fails, but Chrome allows the second (standard
) request to send anyway - Firefox does not. I presume this is actually a bug on behalf of Chrome, but at least it has allowed me to work out that my script is probably working correctly.Here is the first (preflight) request as seen in Chrome and FF:
OPTIONS /frog/LOTS/upload/php.php HTTP/1.1 Host: staff.curriculum.local User-Agent: Mozilla/5.0 (Windows NT 6.1; rv:14.0) Gecko/20100101 Firefox/14.0.1 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip, deflate Connection: keep-alive Origin: http://frogserver.curriculum.local Access-Control-Request-Method: POST Access-Control-Request-Headers: cache-control,x-requested-with Pragma: no-cache Cache-Control: no-cache
The
Access-Control...
headers are those that I've added to IIS.And here are my response headers:
HTTP/1.1 403 Forbidden Content-Length: 1758 Content-Type: text/html Server: Microsoft-IIS/6.0 x-powered-by: ASP.NET Access-Control-Allow-Origin: http://frogserver.curriculum.local Access-Control-Allow-Credentials: true Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Cache-Control Access-Control-Allow-Methods: OPTIONS, GET, POST Access-Control-Expose-Headers: Origin, X-Requested-With Date: Mon, 22 Apr 2013 15:19:20 GMT
I've tried to compare the two side by side but I can't find any missing headers which would cause the
preflight
request to return a403 Forbidden
error.I haven't included my PHP source as it's a lot of code. Suffice to say that it does work in Chrome and that the file is correctly uploaded, so the script should be correct. The only thing which may be worth mentioning is that I've got a
header("Content-Type: text/plain");
at the start of my script. Changing that totext/html
makes no difference to Chrome nor FireFox.The JavaScript is quite straightforward:
$('#jquery-wrapped-fine-uploader').fineUploader({ request: { endpoint: 'http://staff.curriculum.local/frog/LOTS/upload/php.php' }, cors: { expected: true, //all requests are expected to be cross-domain requests sendCredentials: true //if you want cookies to be sent along with the request } });
Can anyone help? I've spent literally 8 hours on this single problem today and I'm >< close to ripping my own face off....!!
Thanks in advance,
-
Ray Nicholus about 11 yearsThis really doesn't seem to be a Fine Uploader issue to me. You might want to change one of your tags to IIS. Fine Uploader is not involved (much) here at all. The user agent sends the OPTIONS (preflight) request, not Fine Uploader. For some reason, your server is rejecting this request with a 403. You might want to take a look at your server logs to see why it is responding with 403.
-
Bigood about 11 yearsOnce again, +1 for the well asked question!
-
turbonerd about 11 years@RayNicholus you're correct, it's not an issue with Fine Uploader, but I think it'd be wrong to say that it isn't relevant. Does Fine Uploader determine the headers that the preflight request sends?
-
Ray Nicholus about 11 years@dunc No, Fine Uploader has no involvement in the preflight request. It is handled completely by the user agent.
-
turbonerd about 11 yearsOK @RayNicholus, thanks. Do you know, then, what determines the headers for the preflight request?
-
Ray Nicholus about 11 years@dunc Are you asking about the Access-Control-Request-Headers value? Any non-standard headers in the proposed CORS request will be in this header field. This is one thing that triggers the UA to pre-flight the request (non-standard headers in a CORS request). I wrote a blog post on CORS support in Fine Uploader. I have also linked to an MDN article that talks about CORS in general in some more detail.
-
inf3rno about 11 yearsDoes your IIS serve OPTIONS request by non CORS requests? stackoverflow.com/questions/6656354/… I have a similar application with IIS7 without credentials, I checked your headers, these are the difference: Access-Control-Allow-Credentials, Access-Control-Allow-Headers, Access-Control-Expose-Headers, Access-Control-Request-Headers, so if the problem is with the headers you should check these... You should upgrade to IIS7 I think if it is a dev server, I have no problems with OPTIONS requests, but I never needed credentials.
-
turbonerd about 11 yearsThanks @inf3rno you were along the right lines - I've just posted the answer.
-
-
turbonerd about 11 yearsI have read both your blog and your article, but neither helps me rectify this problem. From what I can see in the requests/responses according to my browser, the preflight request should work - the header and method are both allowed by the server.
-
Ray Nicholus about 11 years@dunc Is your server expecting some cookies to be sent along with the request in order to authenticate the request? If so, this is your problem. Preflight requests will not include cookies, per the spec.
-
Ray Nicholus about 11 years... see w3.org/TR/cors/#cross-origin-request-with-preflight-0 for more details.
-
turbonerd about 11 yearsHi again Ray. I've tried setting
sendCredentials
tofalse
and removing the credentials header from IIS, but I'm getting exactly the same results. -
Ray Nicholus about 11 years@dunc it doesn't sound like you have understood my last comment. Let me rephrase. My guess is that your server is expecting credentials to be sent with the options request. This will never happen, per the spec. This would perhaps explain the 403.
-
turbonerd about 11 yearsHm, you're right then, I don't. What determines whether the server expects credentials to be sent?
-
turbonerd about 11 yearsThe code is nothing other than that provided by Fine Uploader, Ray. I haven't amended either that JavaScript or the PHP at this point. I've used the exact
php.php
file bundled in the server-side examples on your GitHub page. As such, I have literally no clue where to begin. -
Ray Nicholus about 11 yearsSince you had the same exact issue pre-Fine Uploader, perhaps there is something server-side that your are overlooking. There's no question that your server is rejecting the OPTIONS request. I'm not sure anyone can give you any additional suggestions. You will need to figure out what code or settings on your server are rejecting this request, but the credential-related suggestion I have given seems like a logical explanation.
-
turbonerd about 11 yearsI'm sure someone that understands CORS (and potentially PHP, if it's a server-side issue) could point me in the direction of where the code may be going wrong. The code written in my previous question was also a pre-written file bundled with pluploader and I'm sure that both it and Fine Uploader's PHP script worked correctly on other systems... so what could be the difference between those systems and my own? That's what I'm now looking for help with.
-
Ray Nicholus about 11 yearsI understand CORS pretty well. This is, without a doubt, a server-side issue. I'm not sure what other advice can be offered. It seems like a simple problem. Your server is rejecting the OPTIONS request. You are simply going to have to spend some time and follow the request as it hits your server and figure out why your server is responding with a 403.
-
inf3rno about 11 yearsYe, but this issue is a duplicate, as I linked before: stackoverflow.com/questions/6656354/… Only MSIE 10+ supports CORS, that's why it is not working in IE... Below that version you have only an useless XDomainRequest with very limited functions...
-
turbonerd about 11 yearsYou posted your link, seemingly, as I was writing my answer out.. :) I'm sure you're right, but the file upload cross-domain is now working in every browser with FineUploader, so I'm happy.
-
Ray Nicholus about 11 years@inf3rno This issue is not similar to the issue you have linked to. Fine Uploader doesn't use xhr or xdomain request for file uploading in ie9 or older. Instead, a form inside a hidden iframe is submitted. Message passing is used to get around the cross domain issue when attempting to parse the response client side. This does mean that cors requests for uploads are not supported in ie7 and older though.
-
PAA over 8 yearsCould anyone please respond on this error stackoverflow.com/questions/32725249/…? I really need help