12

I just started fiddling around with OWIN/Katana and MVC.NET 5.0. The default Visual Studio 2013 ASP.NET Web Application/MVC Template has an AccountController with a LogOut() action:

public ActionResult LogOff() {
    AuthenticationManager.SignOut();
    return RedirectToAction("Index", "Home");
}

As expected, this works just fine. However, when I change the response status code, e.g. by:

    Response.SetStatus(HttpStatusCode.SeeOther);

... The AuthenticationManager.SignOut() method no longer causes the user to become logged off. Why is that?

I tried different approaches for setting the http status code for the response, as well as changing http headers like Location, and always with the same result - the user is not logged off when the LogOff() action is executed, if I get into tempering with the response.

I tried not using RedirectToAction (which explicitly implements a 302 redirect - that's another story), and not returning an ActionResult, but that made no difference - not that I'd really expect it to.

Using Fiddler I can tell that the response as it appears to the browser looks fine, not holding any surprises.

I also tried looking through the source code of the OWIN middleware at work, but the architecture is still unfamiliar to me, and I found no answers that I could grasp in there. I need your help in sorting this out, so thank you in advance!

Oskar Lindberg
  • 2,255
  • 2
  • 16
  • 36
  • When the response goes back to the client in fiddler, do you see the Set-Cookie to remove the old cookie? – Brock Allen Dec 13 '13 at 15:45
  • No. I Agree that this is the technical reason why the user is still treated as logged on. What I do not get is why the call to SignOut() shouldn't give the same result regardless if I change the status code or not, removing the cookie and all. I could remove the cookie by myself, or If I wanted a different behavior all together I could even implement my own OWIN middle-ware, but I don't. I just want another status code, which perhaps is contradictory to the behavior implemented with RedirectToAction, but why should the AuthenticationManager care? Am I all backwards in this? – Oskar Lindberg Dec 13 '13 at 18:23
  • After the next request, is the user logged off? – Travis J Dec 16 '13 at 17:49
  • @Travis: No. The cookie is still there, and the user is still logged on. – Oskar Lindberg Dec 17 '13 at 07:54

2 Answers2

7

The reason AuthenticationManager.SignOut() fails is that Response.SetStatus(HttpStatusCode.SeeOther) internally ends the response:

public static void SetStatus(this HttpResponseBase response, int httpStatusCode)
{
  response.StatusCode = httpStatusCode;
  response.End();
}

(See System.Web.WebPages.ResponseExtensions)

After this, naturally the ResponseManager cannot manipulate the response to remove cookies etc.

Oskar Lindberg
  • 2,255
  • 2
  • 16
  • 36
2

This works fine for me with the following LogOut method, are you doing something slightly differently?

    //
    // POST: /Account/LogOff
    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult LogOff()
    {
        Response.StatusCode = 303;
        AuthenticationManager.SignOut();
        return RedirectToAction("Index", "Home");
    }
Hao Kung
  • 28,040
  • 6
  • 84
  • 93
  • Thanks for your reply, Hao. Two things: First, the code above does not change the status code of the response (which is somewhat annoying in itself). It's actually still a 302 response that gets returned (see Fiddler); Second, yes, as you can see from my example code I do Response.SetStatus(HttpStatusCode.SeeOther); – Oskar Lindberg Dec 17 '13 at 07:20
  • The reason why your code does not work is that RedirectToAction() changes the status code again to 302. I went back to check what Response.SetStatus() does to prevent this from happening, and it actually executes a Response.End(). If you do the same in your code, you'll get the exact same result - the user is not logged out. Now the reason has become clear though - of course the AuthenticationManager cannot perform a sign out, removing cookies and stuff, after the response has been "ended", right? :) This is actually the answer to my question, I guess... Can't believe I overlooked this... – Oskar Lindberg Dec 17 '13 at 07:39
  • Try this after remembering your password.. It fails to work (see my answer) to resolve this – Jimmyt1988 Apr 07 '15 at 15:37