14

I am struggling for hours now. I want to make a simple ajax request to another domain, but get http 401 Error all the time:

jQuery(document).ready(function($){
  var challengeid = $('#codepressHook').data('challengeid');
  var clicked = false;
  $('#codepressHook').click(function(){
    if(!clicked){
      $.ajax({
        url: "https://dev.radbonus.com/admin/affiliate-connections/retrieveSingle/"+challengeid+".json",
        method: "GET",
        dataType: "json",
        jsonp: false,
        contentType: "application/json",
        xhrFields: {
          withCredentials: true
        },
        beforeSend: function(xhr){
          xhr.setRequestHeader("Authorization", "Basic "+ btoa(username+":"+password));
        },
        success: function(data){
          $('#codepressHock').html(data.data.code);
        },
        error: function(error){
          alert(error);
        }
      });
    }
  });
});

I set all relevant CORS headers on the serverside. Here is the network traffic:

Request URL:https://dev.radbonus.com/admin/affiliate-connections/retrieveSingle/45.json
Request Method:OPTIONS
Status Code:401 Unauthorized
Remote Address:185.102.94.230:443
Referrer Policy:no-referrer-when-downgrade

Response Headers
view source
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:Content-Type, X-Requested-With, Authorization, Origin
Access-Control-Allow-Methods:POST, GET, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:http://radbonus.com
Access-Control-Max-Age:31536000
Content-Length:463
Content-Type:text/html; charset=iso-8859-1
Date:Sat, 24 Jun 2017 11:25:33 GMT
Server:Apache/2.4.18 (Ubuntu)
WWW-Authenticate:Basic realm="Admin"

Request Headers
view source
Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:authorization,content-type
Access-Control-Request-Method:GET
Connection:keep-alive
Host:dev.radbonus.com
Origin:http://radbonus.com
Referer:http://radbonus.com/plugintest/
User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36

I know that there are a lot of posts on this topic, but it seems I'm missing something simple. Could anyone help me?

lance dörksen
  • 193
  • 1
  • 2
  • 8
  • 2
    The server backend of https://dev.radbonus.com needs to be configured to respond to OPTIONS requests with a 200 or 204 success message, at least for requests from http://radbonus.com and at least for the requests for the path '/admin/affiliate-connections/retrieveSingle/45.json'. You probably want to use https://stackoverflow.com/posts/44735921/edit to update/edit the question to add details about what software is running on the backend of https://dev.radbonus.com—because without that information, nobody here is going to be able to help you much further – sideshowbarker Jun 24 '17 at 11:52
  • I see. Do you know how to do that with haproxy? Because I can't find anything like that in web. – lance dörksen Jun 24 '17 at 17:17

4 Answers4

23

UPDATE Looks like I was not right. Authorization header is never sent for OPTIONS request. Please see comment by sideshowbarker - you need to make sure that your server doesn't respond with 401 to OPTIONS request.

I don't know what language is your server written in, but you implemented authorization in the wrong way - OPTIONS method should be excluded from auth. Also see here - OPTIONS request authentication

Below is obsolete answer:

Your serverside requires HTTP Basic authentication for this request. And you don't provide credentials. 401 error has nothing to do with CORS; it just means that the server chose to not authorize your request because you didn't provide auth credentials.

If you try to open this url (like https://dev.radbonus.com/admin/affiliate-connections/retrieveSingle/1.json) directly in browser, you will be asked to enter login&password, which is how the browser handles 401 error with WWW-Authenticate header.

Please notice that Authorization header is actually not included with your request. So instead of using beforeSend hook, you should probably just include header directly in your call:

headers: {
    'Authorization': 'Basic ' + btoa(username+':'+password),
},

And make sure that Authorization header presents in your request.

MarSoft
  • 3,555
  • 1
  • 33
  • 38
  • But why doesn't it add the header, even though I provide it in the before sending callback? – lance dörksen Jun 24 '17 at 11:58
  • My bad, I didn't notice that you cited headers for `OPTIONS` method. It never includes Authorization header. So you should tweak your server to allow OPTIONS requests without authorization. Please see updated answer. – MarSoft Jun 24 '17 at 12:31
4

Browsers make a Pre-flight request with method - OPTIONS, with the header names(only) you will be sending for actual request, before the actual GET/POST/PUT method. That is why your Pre-flight request headers looks like this,

**Access-Control-Request-Headers:authorization,content-type**

Now, in your Server, you should return HTTP_STATUS.OK - 200, for the OPTIONS request. If it returns any other status, then your actual request won't be made to server.

Here is a Good reading on CORS. https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

I've faced this same issue recently and fixed by returning, 200 for the OPTIONS method in my Servlet Filter(SpringBoot).

Manikandaraj Srinivasan
  • 3,557
  • 5
  • 35
  • 62
0

You should check if you have disabled "Anonymous Authentication" in order to allow any authentication like "Windows Authentication". If you disabled it you will get 401 for any preflight request since they don't send credentials in their request.

You should enable "Anonymous Authentication" and use "Authorization Rules" section in IIS to avoid anonymous access. in case you don't have it, you can install it in windows features under the section:

Internet Information Services(IIS) - World Wide Web Services - Security - URL Authorization

You can for example set your authorization rules like this: enter image description here enter image description here

You can read more about it here

MasterPiece
  • 445
  • 7
  • 13
-3

Please add cross domain in headers like this:

$.ajax({
        url: "https://dev.radbonus.com/admin/affiliate-connections/retrieveSingle/"+challengeid+".json",
        method: "GET",
        dataType: "json",
        jsonp: false,
        contentType: "application/json",
        xhrFields: {
          withCredentials: true
        },
        crossDomain: true,
        beforeSend: function(xhr){
          xhr.setRequestHeader("Authorization", "Basic "+ btoa(username+":"+password));
 xhr.setRequestHeader("Access-Control-Allow-Origin",'*');
        },
        success: function(data){
          $('#codepressHock').html(data.data.code);
        },
        error: function(error){
          alert(error);
        }
      });
Pramod
  • 11
  • 2
  • 9
    Hey, but `Access-Control-Allow-Origin` should be set from server side, not from client side, right? And it is already set. – MarSoft Jun 24 '17 at 12:26