14

I was reading about CORS requests, and I have managed to make regular GET or POST request and it works fine. But when I add authorization header to a either GET or POST request, then the preflight OPTIONS request is sent to the server and I get 500 INTERNAL SERVER ERR, and the actual request isn't sent. My question is how does the preflight actually work, and what response does it require so that it will send the main request? And is it possible to send it without the preflight because I'm sure that then it would work? The serve-rside is written in Django 1.6 and has ACCESS-ALLOW-ORIGIN set to *, and it works with regular post and get requests.

This is my JS code:

 $.ajax({
  type: "GET",
  url: "http://url/login/",
  async:false,
  contentType: "application/json",
  headers: {
    "Authorization": "Basic " + btoa(loginName + ':' + password),       
  },
  success: function (data) {
    alert("OK!");
  },
  failure: function(errMsg) {
    alert(errMsg);
  }
});

These are the headers from Chrome DevTools when the request is executed: Request headers:

OPTIONS /login/ HTTP/1.1
Host: url
Connection: keep-alive
Access-Control-Request-Method: GET
Origin: null
User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko)     Chrome/36.0.1985.125 Safari/537.36
Access-Control-Request-Headers: accept, authorization, content-type
Accept: */*
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8,hr;q=0.6,sr;q=0.4

Response headers:

HTTP/1.1 500 INTERNAL SERVER ERROR
Date: Thu, 31 Jul 2014 16:15:19 GMT
Server: Apache/2.2.15 (CentOS)
X-Frame-Options: SAMEORIGIN
Access-Control-Allow-Origin: *
Connection: close
Transfer-Encoding: chunked
Content-Type: text/html; charset=UTF-8
Matija
  • 453
  • 2
  • 5
  • 13

1 Answers1

27

To pass authorization headers you must set Access-Control-Allow-Credentials to true.

The problem is that, according to specification (MDN explains it simpler), if Access-Control-Allow-Credentials is set to true, Access-Control-Allow-Origin cannot contain *, therefore allowing any hosts making requests with credentials attached.

There are two options to solve this problem:

  • Set Access-Control-Allow-Origin to actual host making requests
  • If there are more than one host: "canonical" way would be to have a whitelist of hosts in application itself, than check Origin header if it's on the list and adding Origin as Access-Control-Allow-Origin header value.

With Django, check for Origin and adding a header can be made in Middleware, but that would make a decent question on it's own (and probably have been already asked)

J0HN
  • 26,063
  • 5
  • 54
  • 85
  • What is the best options for the following case ? Need to send Get request with cross domain origin with header authentication. Its working fine in chrome and firefox , but having issue in safari and IE also in random cases it returns 401. IE do not support user name and password in URL https://support.microsoft.com/en-in/kb/834489 – magento2new Dec 23 '16 at 09:22
  • @p4pravin Is passing username and pass in url an absolute "must happen" requirement from backend system (i.e. the one you're sending the request to)? If not, maybe it would work better using `Authorization` header. – J0HN Dec 27 '16 at 06:08
  • John , its not a must requirement , but i am using bigcommerce and trying to get the data from other server and so i found only ajax jsonp will be helpful in this case and if i pass using authorization , the jsonp call is changing the type to "options" , if i change the header for authorization and which is not working for jsonp call , as it only support get , i believe. – magento2new Dec 27 '16 at 08:00
  • @p4pravin I'd suggest you post this as a separate question than. – J0HN Dec 27 '16 at 08:36
  • Thanks John, I already have separate question now http://stackoverflow.com/questions/41296328/cross-domain-request-with-header-authentication – magento2new Dec 27 '16 at 08:45