Browser equivalent to IE’s ClearAuthenticationCache

asp.netauthenticationcross-browser

I have a few internal .net web application here that require users to "log out" of them. I know this may seem moot on an Intranet application, but nonetheless it is there.

We are using Windows authentication for our Intranet apps, so we tie in to our Active Directory with Basic Authentication and the credentials get stored in the browser cache, as opposed to a cookie when using .net forms authentication.

In IE6+ you can leverage a special JavaScript function they created by doing the following:

document.execCommand("ClearAuthenticationCache", "false")

However, for the other browsers that are to be supported (namely Firefox at the moment, but I strive for multi-browser support), I simply display message to the user that they need to close their browser to log out of the application, which effectively flushes the application cache.

Does anybody know of some commands/hacks/etc. that I can use in other browsers to flush the authentication cache?

Best Answer

I've come up with a fix that seems fairly consistent but is hacky and I'm still not happy with it.

It does work though :-)

1) Redirect them to a Logoff page

2) On that page fire a script to ajax load another page with dummy credentials (sample in jQuery):

$j.ajax({
    url: '<%:Url.Action("LogOff401", new { id = random })%>',
    type: 'POST',
    username: '<%:random%>',
    password: '<%:random%>',
    success: function () { alert('logged off'); }
});

3) That should always return 401 the first time (to force the new credentials to be passed) and then only accept the dummy credentials (sample in MVC):

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult LogOff401(string id)
{
    // if we've been passed HTTP authorisation
    string httpAuth = this.Request.Headers["Authorization"];
    if (!string.IsNullOrEmpty(httpAuth) &&
        httpAuth.StartsWith("basic", StringComparison.OrdinalIgnoreCase))
    {
        // build the string we expect - don't allow regular users to pass
        byte[] enc = Encoding.UTF8.GetBytes(id + ':' + id);
        string expected = "basic " + Convert.ToBase64String(enc);

        if (string.Equals(httpAuth, expected, StringComparison.OrdinalIgnoreCase))
        {
            return Content("You are logged out.");
        }
    }

    // return a request for an HTTP basic auth token, this will cause XmlHttp to pass the new header
    this.Response.StatusCode = 401; 
    this.Response.StatusDescription = "Unauthorized";
    this.Response.AppendHeader("WWW-Authenticate", "basic realm=\"My Realm\""); 

    return Content("Force AJAX component to sent header");
}

4) Now the random string credentials have been accepted and cached by the browser instead. When they visit another page it will try to use them, fail, and then prompt for the right ones.