Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make XMLHttpRequest cross-domain withCredentials, HTTP Authorization (CORS)?

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?

like image 464
edA-qa mort-ora-y Avatar asked Feb 18 '14 10:02

edA-qa mort-ora-y


People also ask

Does XMLHttpRequest support CORS?

The CORS mechanism supports secure cross-origin requests and data transfers between browsers and servers. Modern browsers use CORS in APIs such as XMLHttpRequest or Fetch to mitigate the risks of cross-origin HTTP requests.

What does XHR withCredentials mean?

The XMLHttpRequest. withCredentials property is a boolean value that indicates whether or not cross-site Access-Control requests should be made using credentials such as cookies, authorization headers or TLS client certificates.

How do I set mode in XMLHttpRequest?

XMLHttpRequest does not support no-cors mode, only fetch does. However, you are trying set a Content-Type of application/json which requires permission from CORS, so you can't use no-cors mode anyway. If you used fetch and set no-cors mode then the instruction to set the Content-Type would be ignored.


1 Answers

I've written an article with a complete CORS setup.

I found several issues that can result in this problem:

  1. The Access-Control-Allow-Origin cannot be a wildcard if credentials are being used. It's easiest just to copy the Origin header of the request to this field. It's entirely unclear why the standard would disallow a wildcard.
  2. 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 header Access-Control-Max-Age: 1
  3. The username/password of the open command is apparently not usable as the credentials. You must add an Authorization 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.

like image 78
edA-qa mort-ora-y Avatar answered Sep 25 '22 17:09

edA-qa mort-ora-y