views:

871

answers:

2

I am using jQuert .ajax function to call a page method. The site is using FormsAuthentication. So when an authentication ticket expires a call to the page method will obviously cause a redirect to the login page.

Now, the geniuses that wrote the System.Web.Handlers.ScriptModule decided that if for some reason a REST style call to a page method or a web service method, from JavaScript causes a 302 Redirect, they're going to just simply turn the response into a 401 Unauthorized. This causes a browser to popup a login UI that is totally misleading, as the user tries to type in their username and password, which means nothing, because FormsAuthentication is used. Finally, when the user clicks Cancel, the 401 comes through to the error handler.

So, the question is, how can one disable the browser's login UI prompt in any way? Some people on the web suggest to use a username and password in the XHR request, but it does not seem to work.

+3  A: 

I think I worked around it. Ofcourse relying on internal MS AJAX related errors is not really nice, but this will do the trick for others faces with this problem.

Basically what you do, is you set the X-MicrosoftAjax header to the value Delta=true (case is important here), the ScriptModule will interpret this as a normal redirect, and turn the response into a 200, but will set the pageRedirect data string for any ScriptManager (MS-AJAX PageRequestManager) on the page to consume. The jQuery.ajax function will still see this as an error, so basically you can check for pageRedirect in responseText property of the XHR and hadle it accordingly. Like sending the user to the login page of something.

    $.ajax({
            type: "POST",
            url: postUrl + "/SomePageMethod",
            data: "{searchString:\"" + escape(searchString) + "\"}",
            contentType: "application/json; charset=utf-8",
            beforeSend: function(xhr) {
                xhr.setRequestHeader("X-MicrosoftAjax","Delta=true");
            },
            dataType: "json",
            success: onSuccess,
            error: onError
        });

function onError(xhr, e, textStatus) {
    var isAjaxRedirect = xhr.status == 200 && xhr.responseText.match(/pageRedirect/);
    if (isAjaxRedirect == "pageRedirect") {
        // forms authentication ticket expired
        location.href = "a session timeout page, or a login page or whatever";
    }
}
Strelok
i don't quite get it. you're doing something at the server to turn your 401s into 200s? that doesn't help if you're not using the microsoft stack or you don't have access to the server. i need a browser-only solution.
landon9720
Well the *problem* is specific to using the Microsoft stack AND the solution is browser only. Not sure what your particular problem is though.
Strelok
A: 

Thanks! This was a big help.

JP