JQuery Ajax calls with HTTP Basic Authentication

Dylan picture Dylan · Mar 13, 2012 · Viewed 42.5k times · Source

I have a REST based server which I am trying to communicate with using JQuery. Both XML and JSON are available as response formats, so I am using JSON.

The connections are all SSL so HTTP Basic Authentication has been our authorization method of choice, and we have had no problems with other front ends (raw Javascript, Silverlight, etc...)

Now I am attempting to put something together with JQuery and having endless problems using HTTP Basic Authentication.

I have scoured through numerous previous questions most of which either have solutions that do not seem to actually work or blame the entire problem on cross origin access, which I have already overcome in basic Javascript testing. The responses always provide Access-Control-Allow-Origin set to the provided Origin header in the request, and this can be seen in the responses of my tests.

In basic javascript, this entire call is very simply accomplished with:

req.open('GET', 'https://researchdev-vm:8111/card', true, 'test', 'testpassword');

The JQuery attempt at this is fairly standard:

        $.ajax({
        username: 'test',
        password: 'testpassword',
        url: 'https://researchdev-vm:8111/card',
        type: 'GET',
        dataType: 'json',
        crossDomain: true,
        /*data: { username: 'test', password: 'testpassword' },*/
        beforeSend: function(xhr){
            xhr.setRequestHeader("Authorization",
                //"Basic " + encodeBase64(username + ":" + password));
                "Basic AAAAAAAAAAAAAAAAAAA=");
        },
        sucess: function(result) {
            out('done');
        }
    });

The only method that actually seems to work to provide authentication is the direct insertion of the Base64 encoded data in the beforeSend() function. If this is not included, there is no progress made whatsoever. Username and password properties seem to be ignored entirely.

With the beforeSend() behavior provided, the GET call gets a positive response with data included. However, because this is a cross site call, an OPTIONS call is performed ahead of the GET call and always fails, because it does not make use of beforeSend() and therefore gets a 401 response due to failed authentication.

Is there a better way to accomplish what should be a very trivial call? Should the fact that the OPTIONS request does not make use of the beforeSend() function processing be considered a bug? Is there perhaps a way to disable the OPTIONS check entirely? It is not possible to make this call not cross-site, as Javascript seems to consider even a different port number on the same machine as "cross-site".

Answer

jmillar picture jmillar · Nov 27, 2012

This question is probably well past its' expiry date, but I was working with the same thing with Jquery and came across the same problem.

The username and password attributes do not seem to do a base64 encode of the username/password as you do to normally accomplish HTTP basic auth.

Look at the following requests (shortened for brevity), firstly using the "username" and "password" parameters in the JQuery AJAX method:

Request URL:http://testuser%40omnisoft.com:testuser@localhost:60023/Account
Request Method:GET
Accept:application/json, text/javascript, */*; q=0.01
Host:localhost:60023

And now with the beforeSend method:

Request URL:http://localhost:60023/Account
Request Method:GET
Accept:application/json, text/javascript, */*; q=0.01
Authorization:Basic dXNlcm5hbWU6cGFzc3dvcmQ=
Host:localhost:60023

Note that the first method does not include an 'Authorization' header in the request, but instead prefixes the target URL. I'm no expert on HTTP basic auth, but it would indicate that the former is not a proper implementation and therefore fails (or at least it does with my own server implementation).

As to your OPTIONS request using JSONP - you could possibly try using ?callback=? in your URL instead of using the crossdomain option, just to be explicit.