I have an MVC 4 application that uses Windows Authentication. My current challenge is I need to provide a logout button for users. I can acheive this in straight Chrome, in straight IE, but when I add the Google Chrome Frame(GCF) into the mix, I seem to have issues.
I'm using IE9 with GCF.
When I try and send out the AJAX request, this is what the GCF network trace is telling me:
Request:
GET http://103581:107674@linkToMySite/LogOff401?_=1369312905224 HTTP/1.1
Accept: */*
Referer: http://LinkToMySite
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.93 Safari/537.36
Authorization: user:pass
Unfortunately the response fails. The Chrome developer tools picks it up, but I think that IE is blocking the request from going out as Fiddler doesn't see it. I'm at a loss and have been troubleshooting this for a number of days, unsure if this is something I should report to Google as a bug.
This is the client side logout code (an adaptation from here http://trac-hacks.org/wiki/TrueHttpLogoutPatch) :
function LogMeOut(url) {
try {
document.execCommand("ClearAuthenticationCache");
SendAJAXLogout(url);
}
catch(err){
try {
SendAJAXLogout(url);
} catch(err) {
log("Unable to log this user out.");
}
}
window.location.href = url;
}
function SendAJAXLogout(url) {
$.ajax(url, {
username: GetRandomNumber(10000, 99999),
password: GetRandomNumber(10000, 99999),
beforeSend: function (req) {
req.setRequestHeader('Authorization', "user:pass");
},
cache: false,
error: function (jqXHR, textStatus, errorThrown) {
//alert("Error: " + textStatus);
log("I'm logged out now");
}
});
}
This is the server side action method that I got elsewhere but cannot find the link (I did not write this):
[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");
}