Ruby on Rails | Screencasts | Download | Documentation | Weblog | Community | Source

Ticket #6638 (closed defect: fixed)

Opened 2 years ago

Last modified 2 years ago

[PATCH] Safari HTTP auth problem because of changes in Ajax

Reported by: jmecham Assigned to: sam
Priority: high Milestone: 1.2 regressions
Component: Prototype Version:
Severity: critical Keywords: ajax safari http authentication
Cc: mislav, madrobby

Description

r5448 added code to allow the specification of a username and password to use for an XMLHTTPRequest, but even if values are not provided they are added to the request. In Safari, this defaults to "undefined" resulting in requests to http://undefined:undefined@example.com/ (which breaks my custom HTTP Authorization header set with "requestHeaders" ('Authorization: Basic XXXXXXXXX').

The username and password should not be set for the request if they have not been specified.

Attachments

conditionally_pass_username_and_password_patch.diff (0.9 kB) - added by jmecham on 11/17/06 15:59:42.
ajax-auth-6658.diff (3.4 kB) - added by madrobby on 12/10/06 01:13:47.
for playing with the authorization header

Change History

11/17/06 15:59:42 changed by jmecham

  • attachment conditionally_pass_username_and_password_patch.diff added.

11/17/06 16:06:29 changed by jmecham

I have also come across #4192 which looks to be identical to my patch and should also be closed with this bug if this patch is accepted (and perhaps closed in general because username and password can now be specified as of r5448).

11/17/06 17:10:42 changed by mislav

  • cc set to mislav.
  • keywords set to ajax safari http authentication.
  • summary changed from [PATCH] XMLHTTPRequests include username and password of "undefined" in Safari to [PATCH] Safari HTTP auth problem because of changes in Ajax.
  • priority changed from normal to high.

Perhaps something like this is better:

var args = [this.options.method.toUpperCase(),
  this.url, this.options.asynchronous]

if(this.options.username) args.concat(
  [this.options.username, this.options.password || ''])

this.transport.open.apply(this.transport, open_args)

It's prettier and you don't have to specify a password if you want to send an empty one.

Thanks for the report!

12/05/06 14:04:10 changed by manfred

This doesn't just break when you create a custom Ajax request, if also breaks requests with all the ajax helpers.

12/05/06 17:32:00 changed by bitsweat

  • cc changed from mislav to mislav, madrobby.
  • keywords changed from ajax safari http authentication to ajax safari http authentication 1.2regression.
  • milestone changed from 1.x to 1.2.

12/05/06 18:20:06 changed by madrobby

We should definetely come up with a method of testing this, should be reasonably doable with the automatic unit tests and some hackery to the WEBRick thingy it uses. I'd gladly apply this, currently I'm a bit out of time to write those myself.

(in reply to: ↑ description ) 12/05/06 21:40:45 changed by jshell

Replying to jmecham:

r5448 added code to allow the specification of a username and password to use for an XMLHTTPRequest, but even if values are not provided they are added to the request. In Safari, this defaults to "undefined" resulting in requests to http://undefined:undefined@example.com/ (which breaks my custom HTTP Authorization header set with "requestHeaders" ('Authorization: Basic XXXXXXXXX'). The username and password should not be set for the request if they have not been specified.

I need this patch, or something like it, to be applied soon.

I just updated to the new version of Scriptaculous (1.6.5) for my web application, which is built on Zope 3, not Rails. Zope 3 and its predecessors have long had a rich security model and easy support for HTTP Auth, so I make use of it quite often. Since applying Scriptaculous 1.6.5, which uses a version of Prototype.js that includes the Ajax username/password changes, my application pops up authentication challenges all over the place and they're hard to get rid of. Prior to these changes, the browser sent along the same authentication credentials it would send along to any other resource that requested authentication. I need that behavior to continue. I don't have access to a users name and password, and would hate to have to send it along in a rendered page in plain text if I did. If the browser and underlying server software are taking care of authentication for me already, I shouldn't have to manually specify the username and password with every XMLHttpRequest any more than I'd have to specify it on every link that pointed to an image or CSS file or page that required authentication.

12/10/06 01:12:40 changed by madrobby

I've investigated a bit further here. First thing, of course the patch needs to be applied as it breaks Safari. mislav: note that your approach seems to fail (the apply() call seems to have a bug with Safari when used with XMLHttpRequest.open).

On the other hand, the username/password combination given to XMLHttpRequest.open() doesn't do anything (tested Firefox on Safari). It does _not_ send along the credentials. If I manually add an Authorization header, it works. Because of this, I propose to remove the username/password option completely. Note that the test case in #4192 doesn't work for me either (when using the open() method)-- keep in mind to completely close the browser between tests to clear out the auth cache.

I'm adding a patch here, for playing around with this. Let me know what you think. If anyone can come up with an explanation, please do so-- I'm out of guessing.

Note: to play around with the patch, apply, then do:

$ rake test_units TESTS=ajax BROWSERS=firefox

Use firebug to have a look at the headers that get sent.

12/10/06 01:13:47 changed by madrobby

  • attachment ajax-auth-6658.diff added.

for playing with the authorization header

(follow-up: ↓ 9 ) 12/10/06 10:22:07 changed by mislav

Madrobby, thanks for taking time for throughly test this. Your findings are indeed interesting.

How about we keep username/password options and throw in some base64_encode() like this one:

// This code was written by Tyler Akins and has been placed in the
// public domain.  It would be nice if you left this header intact.
// Base64 code from Tyler Akins -- http://rumkin.com

var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

function encode64(input) {
   var output = "";
   var chr1, chr2, chr3;
   var enc1, enc2, enc3, enc4;
   var i = 0;

   do {
      chr1 = input.charCodeAt(i++);
      chr2 = input.charCodeAt(i++);
      chr3 = input.charCodeAt(i++);

      enc1 = chr1 >> 2;
      enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
      enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
      enc4 = chr3 & 63;

      if (isNaN(chr2)) {
         enc3 = enc4 = 64;
      } else if (isNaN(chr3)) {
         enc4 = 64;
      }

      output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + 
         keyStr.charAt(enc3) + keyStr.charAt(enc4);
   } while (i < input.length);
   
   return output;
}

(in reply to: ↑ 8 ; follow-up: ↓ 10 ) 12/10/06 10:44:20 changed by madrobby

Replying to mislav:

How about we keep username/password options and throw in some base64_encode() like this one:

We can-- but should we? The username/password thing is probably a use case not needed by most people. On the other hand base64 en- and decoding could be a nice-to-have for String.prototype. But it seems a bit like a case of featuritis.

(in reply to: ↑ 9 ; follow-ups: ↓ 11 ↓ 12 ) 12/10/06 10:55:03 changed by mislav

Replying to madrobby:

The username/password thing is probably a use case not needed by most people.

Probably. Here's what we can do: throw out the options completely (as you suggested) and create an article on the documentation site (I can take care of that part) describing how to authenticate with the header and providing the base64_(en|de)code for copy/paste. After that we can listen to the feedback of the community and decide upon the issue for release 2.

How does that sound?

(in reply to: ↑ 10 ) 12/11/06 09:51:45 changed by madrobby

Replying to mislav:

How does that sound?

Sounds good to me. :)

(in reply to: ↑ 10 ) 12/18/06 11:10:23 changed by madrobby

Replying to mislav:

Replying to madrobby:

The username/password thing is probably a use case not needed by most people.

Probably. Here's what we can do: throw out the options completely (as you suggested) and create an article on the documentation site (I can take care of that part) describing how to authenticate with the header and providing the base64_(en|de)code for copy/paste. After that we can listen to the feedback of the community and decide upon the issue for release 2. How does that sound?

Btw, wanna look into a patch for this? ;)

12/18/06 12:46:31 changed by madrobby

  • severity changed from normal to critical.

Just to make sure this stays on the top...

12/18/06 21:02:14 changed by madrobby

  • status changed from new to closed.
  • resolution set to fixed.

(In [5741]) Prototype: * Remove support for HTTP authorization in Ajax calls introduced with #6366. Closes #6638 [jmecham]. This fixes a regression issue where Safari wouldnt work with sites that use HTTP authorization schemes, plus it never really worked in the first place-- see #6638 for discussion.

03/04/07 13:43:58 changed by bitsweat

  • keywords changed from ajax safari http authentication 1.2regression to ajax safari http authentication.
  • milestone changed from 1.2 to 1.2 regressions.