How to make XMLHttpRequest cross-domain withCredentials, HTTP Authorization (CORS)?
Solution 1
I've written an article with a complete CORS setup.
I found several issues that can result in this problem:
- The
Access-Control-Allow-Origin
cannot be a wildcard if credentials are being used. It's easiest just to copy theOrigin
header of the request to this field. It's entirely unclear why the standard would disallow a wildcard. - Firefox caches the Access-Control results even if you clear the cache (perhaps for the session). Restarting forced it to do a new
OPTIONS
request. To aid in debugging I added the headerAccess-Control-Max-Age: 1
- The username/password of the
open
command is apparently not usable as the credentials. You must add anAuthorization
header yourself.xhr.setRequestHeader( 'Authorization', 'Basic ' + btoa( user + ':' + pass ) )
Overall the withCredentials
system is rather braindead. It's easier to simply write a server that accepts the authorization as part of the body of the request.
Solution 2
The only way I found that works with preflight requests is:
- Disable autentication for OPTIONS method requets by moving autentication logic to code (e.g. from Apache to PHP).
- Use jQuery
ajax
call withwithCredentials
:
$.ajax({
type: 'POST',
xhrFields: {
withCredentials: true
},
...
});
Surprisingly, if I just set xhr.withCredentials to true
it doesn't work:
$.ajax({
type: 'POST',
beforeSend: function (jqxhr) {
jqxhr.withCredentials = true; // This doesn't work
},
...
});
edA-qa mort-ora-y
I'm an experienced programmer who has worked in numerous domains such graphic rendering, telecommunications, scientific applications, business processes, video games, financial platforms, and development products. For more about programming visit Musing Mortoray, or check out my live stream. If you’d like private mentoring check out my profile at Codementor. I’m the creator of the Leaf programming language.
Updated on August 05, 2020Comments
-
edA-qa mort-ora-y almost 4 years
I'm unable to make a cross-domain request with an Authorization header (testing with Firefox). I have requests working without authentication, but once I set
withCredentials
to true I am no longer able to read the response from the server.On the server I send back these headers (using an
after_request
method in Flask):resp.headers['Access-Control-Allow-Origin'] = '*' resp.headers['Access-Control-Allow-Credentials'] = 'true' resp.headers['Access-Control-Allow-Methods'] = 'POST, OPTIONS' resp.headers['Access-Control-Allow-Headers'] = 'Authorization'
No OPTIONS call is ever actually made by Firefox. On the client I make an XMLHttpRequest call:
var xhr = new XMLHttpRequest() xhr.open( 'POST', 'http://test.local:8002/test/upload', true) xhr.withCredentials = true xhr.onreadystatechange = function() { console.log( xhr.status, xhr.statusText ) } xhr.send(fd)
Without
withCredentials
set the log statement will log the expecting information to the console. Once I set the value however the xhr doesn't allow access and I just write a 0 value and an empty string. I haven't set the authorization header here, but that shouldn't affect my ability to read the result.If I attempt to add a username/password to the "open" command I get a
NS_ERROR_DOM_BAD_URI: Access to restricted URI denied
error.What am I doing wrong?