HTTP Basic Authentication using AJAX
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:
$.ajax ( {
url: “http://abc.com/”,
beforeSend: function (xhr) { xhr.setRequestHeader (“Authorization”, “Basic aDkdjfZy==”); },
succes: function(val) { alert(val); } } );
Base 64 Encoding:
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:
xhr.setRequestHeader(“Authorization”, “Basic ” + encodeBase64 (“username:password”) );
That’s about it. Hope this was useful to you !
Some Updates
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.
February 14th, 2009 at 11:42 am
This doesn’t work.
April 6th, 2009 at 12:03 am
Wouldn’t the login information be visible in the source code?
April 7th, 2009 at 9:38 am
@Andy: If you hard-code it in source code, yes, it will be visible. But you can get that as an input from the user.
July 30th, 2009 at 10:36 pm
How about Digest Authentication?
Have u ever try to implement Digest way, or it’s not possible yet?
July 31st, 2009 at 11:00 am
Hey Kent, digest authentication isn’t possible yet I believe.
September 20th, 2009 at 5:18 am
I am having a really hard time getting this to work. I am trying to build a form that updates my twitter through this. Can you post an example?
September 22nd, 2009 at 9:48 am
Hey Adam, I’m unable to understand what you are trying to do. Can you be more clear?
September 29th, 2009 at 12:52 am
I’m trying to build a simple application to update twitter status. I tried a few different way including the one that you suggested:
$.ajax({
url: ‘http://twitter.com/statuses/update.json’,
status: status,
beforeSend: function(xhr) {xhr.setRequestHeader(“Authorization”, “Basic ” + Base64.encode(username + “:” + password))},
sucess: function(result) {alert(‘done’ + result);}
});
But no matter which way I try, I’m getting the following error:
“Access to restricted URI denied” code: “1012” on my error console. I did some research and is seemed like something to do with cross domain AJAX requests. But I’m wondering how it worked for you.
Can you maybe post a working sample for updating twitter status?
September 29th, 2009 at 8:14 am
@Phani: I have updated the post. Please check the same.
September 29th, 2009 at 7:54 pm
I tried setting the domain property to twitter.com. Still no luck though…
document.domain=”twitter.com”;
Any ideas on what I might be doing wrong?
October 2nd, 2009 at 10:39 am
Try using an iframe to do an HTTP Post to twitter. Set the parent document’s domain to match that of twitter’s & you would be able to execute an onload when twitter returns its result.
January 22nd, 2010 at 7:06 am
Has anyone actually got this working?
January 22nd, 2010 at 5:05 pm
Hi Aswin,
If you please add a snippet of code that you have written for cross domain basic authentication, it will be very helpful.
I tried with the iframe concept, still not working for me 🙁
Please help me out
February 10th, 2010 at 8:53 pm
I cleaned up the base 64 script and have posted it here:
http://gist.github.com/300788
Basically, I just extracted the JavaScript from the example, and then made all of the variables and helper methods private. I exposed the decoder/encoder functions as base64.encode, base64.decode
February 12th, 2010 at 1:11 pm
Pretty cool Tim 🙂
March 15th, 2010 at 6:04 pm
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!
Thanks,
James
May 23rd, 2011 at 2:27 am
[…] the client-side, the basic idea (directly inspired by Aswin Anand’s solution) is to craft the Authorization request header in a beforeSend callback instead of relying on […]
May 23rd, 2012 at 5:30 pm
[…] you have the complete example: http://www.aswinanand.com/2009/01/http-basic-authentication-using-ajax/ Tagged: ajax, authentication, jquery, questions /* * * CONFIGURATION […]