January 8th, 2009

Recently I needed a way for Threaded Tweets to do HTTP basic authentication to try out some stuff. As you probably know by now, it is written in javascript and uses no server side code. So, I had to find out some way to pass basic authentication credentials through the XMLHttpRequest object so that I could be authenticated with the Twitter server.

Turns out that it is pretty simple. If you use FireBug on any website that supports Basic Authentication, you will note that a new HTTP header called ‘Authorization’ is added. It looks like:

Authorization: Basic aDkdjfZy==

Now all you need to do is somehow pass on this header to the XMLHttpRequest object. If you use the native XMLHttpRequest, you can use the setRequestHeader method to do this:

xhr.setRequestHeader(“Authorization”, “Basic aDkdjfZy”);

What if you are using jQuery? Then also its pretty simple. jQuery’s AJAX object allows us to change the XHR object before the AJAX request is sent by setting the “beforeSend” callback; which is done as follows:

One important part of Basic Authentication is that, you need to encode the username and password into Base 64. There are tons of Base 64 encoding tools written on javascript, which you can use. Example below:

Cross-domain GET requests work all the time. The problem is with POST requests. Most browsers don’t allow XHR to POST data to a domain that’s different from the one in which the page is loaded. For this to work correctly, the ‘document.domain’ property must be set correctly.

The second best way to POST to another domain is to use an iframe and submit the form with the iframe as the “target”. Again, to read the result of the iframe, the “document.domain” of the parent and that of the iframe should match. This can be easily set through javascript. Thus, when the form post is done and the page is loaded, its value can be accessed.

Note: Chrome and Safari don’t allow access to iframe’s DOM if its document.domain is different from that of the iframe’s parent.

I’m trying to get this working on my own bit of javascript; it’s running from a local file (and always will be), and I’m using the exact same code as Phani above, except I get 403 (authentication) errors. Any clues why? At the moment I’ve got my own username/password hardcoded in, and I’m pretty sure they’re correct!