8
votes

I have a script running on a web page that needs to use the JQuery $.ajax method (currently using jquery 1.7.2) to submit several GET requests to a service endpoint on a different domain. I have the ajax call working in IE (9, 10, 11), but it fails with a 401 Unauthorized response in Firefox and Chrome. Part of the additional error message in Chrome is "Full authentication is required to access this resource".

My ajax call is setup like this (dataType is "json" for these requests that fail, and async is true):

    $.ajax({
      url: url,
      type: "GET",
      async: isAsync,
      dataType: dataType,
      username: user,
      password: pswd,
      success: function (response, status) {
         // success code here
      },
      failure: function (response, status) {
         // failure code here
      },
      complete: function (xhr, status) {
         // on complete code here
      }
   });

I am passing in the username and password required to access the service and this works in IE. I was understanding that the JQuery ajax function would handle the authentication correctly, so if a response comes back indicating that authorization is required, it would use the credentials that were provided to make that request correctly. Am I missing something here? Do I need to manually add the Authorization header for this to work?

UPDATE: Here is the request, response, and cookie info reported by Chrome and IE via the F12 debugging tools (some info replaced with [...removed...])

Chrome (42.0.2311.90 m)

Response Headers

access-control-allow-credentials:true access-control-allow-origin:[...removed...] access-control-expose-headers: cache-control:private,max-age=0,must-revalidate connection:keep-alive content-encoding:gzip content-length:296 content-type:text/html;charset=ISO-8859-1 date:Tue, 21 Apr 2015 20:55:12 GMT expires:Tue, 21 Apr 2015 20:55:12 GMT p3p:CP="NON DSP COR CURa PSAa PSDa OUR NOR BUS PUR COM NAV STA" set-cookie:JSESSIONID=qd-app-1348vf1vrksvc76oshcwirvjp.qd-app-13;Path=/;Secure;HttpOnly set-cookie:NSC_vt1.sbmmzefw.dpn!-!IUUQT=ffffffff09091c3945525d5f4f58455e445a4a42378b;path=/;secure;httponly status:401 Unauthorized vary:Accept-Encoding version:HTTP/1.1 www-authenticate:Basic realm="Rally ALM"

Request Headers

:host:rally1.rallydev.com :method:GET :path:[...removed...] :scheme:https :version:HTTP/1.1 accept:application/json, text/javascript, /; q=0.01 accept-encoding:gzip, deflate, sdch accept-language:en-US,en;q=0.8 origin:[...removed...] referer:[...removed...] user-agent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.90 Safari/537.36

Response Cookies

JSESSIONID qd-app-1348vf1vrksvc76oshcwirvjp.qd-app-13 NSC_vt1.sbmmzefw.dpn!-!IUUQT ffffffff09091c3945525d5f4f58455e445a4a42378b

IE 11

Request Headers

Request GET [...removed...] Referer [...removed...] Accept
application/json, text/javascript, /; q=0.01 Accept-Language en-US Accept-Encoding gzip, deflate User-Agent Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko Host [...removed...] Connection Keep-Alive Cache-Control no-cache Cookie
JSESSIONID=qd-app-08xmftgye78tde1b0wzcl2kit4m.qd-app-08; NSC_vt1.sbmmzefw.dpn!-!IUUQT=ffffffff09091c3145525d5f4f58455e445a4a42378b; RALLY-Detail-treeCollapsed=false; ZSESSIONID=RpKo5acfRqmjPhW0vIU1rgurWmDhlka0lrGCY9MIWhU; SUBBUCKETID=713

Response Headers

Response HTTP/1.1 200 OK RallyRequestID qd-app-08xmftgye78tde1b0wzcl2kit4m.qd-app-0810353108 Expires Thu, 01 Jan 1970 00:00:00 GMT Content-Type text/javascript; charset=utf-8 ETag "0101c2c8d3463ee3c1a4f950d4142b7d3" P3P CP="NON DSP COR CURa PSAa PSDa OUR NOR BUS PUR COM NAV STA" Cache-Control private,max-age=0,must-revalidate Date Tue, 21 Apr 2015 20:58:17 GMT Connection keep-alive Set-Cookie ZSESSIONID=RpKo5acfRqmjPhW0vIU1rgurWmDhlka0lrGCY9MIWhU;Path=/;Domain=[...removed...];Secure;HttpOnly Set-Cookie SUBBUCKETID=713;Path=/;Domain=[...removed...];Secure;HttpOnly Content-Length 319

Cookies

Sent JSESSIONID qd-app-08xmftgye78tde1b0wzcl2kit4m.qd-app-08
Sent NSC_vt1.sbmmzefw.dpn!-!IUUQT ffffffff09091c3145525d5f4f58455e445a4a42378b Sent RALLY-Detail-treeCollapsed false Sent ZSESSIONID RpKo5acfRqmjPhW0vIU1rgurWmDhlka0lrGCY9MIWhU Sent SUBBUCKETID 713 Received ZSESSIONID RpKo5acfRqmjPhW0vIU1rgurWmDhlka0lrGCY9MIWhU At end of session [...removed...] / Yes Yes Received SUBBUCKETID 713 At end of session [...removed...] / Yes Yes

1
Did you try debugging using developer tools in chrome or firefox?brso05
Look at the network traffic and see what type of request and response you are getting dissect the request and response to see if anything looks different than ie.brso05
401 is usually returned by the server. Are you authenticating against the remote domain (using cookies, HTTP auth, or otherwise?). Your browser may not be sending the required authentication in all cases.arcyqwerty
Yes, I was in the debugging tools in IE and Chrome. Checking the network traffic, I see a couple differences between the two, in IE it looks like there is a session cookie that is getting added as part of the request, I'm guessing this being handled by JQuery ajax because all I'm doing is what you see in my code sample in the original post. The other difference is that in Chrome, there is an additional response header coming back: www-authenticate:Basic realm="Rally ALM". Again, I'd expect that the $.ajax() function is handling this for IE, so what's the hold-up in Chrome and Firefox?AK3800
I think this may be relevant (particularly the section about Chrome's tighter restrictions on when it includes a cookie): stackoverflow.com/questions/2870371/…S McCrohan

1 Answers

7
votes

I came across a jquery forum post that had some additional information regarding this issue. Based on what I found there, I added this to the $.ajax call:

  beforeSend: function (xhr) {
     xhr.setRequestHeader('Authorization', makeBaseAuth(user, pswd));
  }

where makeBaseAuth() uses the btoa() function like this:

   makeBaseAuth: function(user, pswd){ 
      var token = user + ':' + pswd;
      var hash = "";
      if (btoa) {
         hash = btoa(token);
      }
      return "Basic " + hash;
   }

That appears to be working in Chrome now, I'm not getting a login prompt or a 401 response, the request is going through and I get the expected response. I also removed the option xhrFields: { withCredentials: true } as that didn't appear to be necessary. For some reason this isn't working in Firefox yet, and in the Firefox debugger I can't actually get at the javascript to do any decent debugging to see what the problem is, the way this script works is its loaded into a web page as an anonymous script and I don't have any control over that. I have a way to get at the script in IE and Chrome, but not Firefox for some reason. I'll consider this a win just getting it to work in Chrome, thanks to everyone for prodding me in the right direction!