Question

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.

Was it helpful?

Solution

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";
    }
}

OTHER TIPS

This can be disabled in IIS. Details described below are for IIS6 but it shouldn't be hard to find the relevant items for IIS7 and up.

  1. Find the relevant site.
  2. Open the "Directory Security" tab, or relevant tab in your version of IIS
  3. Click "Edit" within "Authentication and access control" section
  4. Un-tick "Integrated Windows authentication"

You should no longer see the popup in your browser and be able to send back the correct status codes as you wish.

Both are great answers. But if your website is hosted in a shared server, you will probably not be able to change IIS settings, so the client side solution rocks. I have been facing the same problem, and this post saves me. My two cents to the solution: In jquery (at least in the latest versions) you can use a parameter called “header” to send this headers without using the “beforeSend” callback, and I think this can be a bit cleaner way for doing the same. You can also add other header info here:

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

I didn’t know about this header “Delta=true”, and after a bit research, it seems to be a header to tell the server that the request you are doing is an asynchronous postback request.

The AJAX call will return an HTTP Status 200 (instead of "Unauthorized" 401) in the “error” callback, meaning that the server request was successful in some way (although authentication fails). A bit strange, but is the way it works.

Hope this helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top