I have a page that when you press 'log out' it will redirect to the login.aspx
page which has a Page_Load
method which calls FormsAuthentication.SignOut()
.
The master page displays the 'log out' link in the top right of the screen and it displays it on the condition that Page.User.Identity.IsAuthenticated
is true
. After stepping through the code however, this signout method doesn't automatically set IsAuthenticated
to false
which is quite annoying, any ideas?
Page.User.Identity.IsAuthenticated
gets its value from Page.User
(obviously) which is unfortunately read-only and is not updated when you call FormsAuthentication.SignOut()
.
Luckily Page.User
pulls its value from Context.User
which can be modified:
// HttpContext.Current.User.Identity.IsAuthenticated == true;
FormsAuthentication.SignOut();
HttpContext.Current.User =
new GenericPrincipal(new GenericIdentity(string.Empty), null);
// now HttpContext.Current.User.Identity.IsAuthenticated == false
// and Page.User.Identity.IsAuthenticated == false
This is useful when you sign out the current user and wish to respond with the actual page without doing a redirect. You can check IsAuthenticated
where you need it within the same page request.
A person is only authenticated once per request. Once ASP.NET determines if they are authenticated or not, then it does not change for the remainder of that request.
For example, when someone logs in. When you set the forms auth cookie indicating that they are logged in, if you check to see if they are authenticated on that same request, it will return false
, but on the next request, it will return true
. The same is happening when you log someone out. They are still authenticated for the duration of that request, but on the next one, they will no longer be authenticated. So if a user clicks a link to log out, you should log them out then issue a redirect to the login page.
I remember having a similar problem and I think I resolved it by expiring the forms authentication cookie at logout time:
FormsAuthentication.SignOut();
Response.Cookies[FormsAuthentication.FormsCookieName].Expires = DateTime.Now.AddYears(-1);
Why are you executing logout code in the login.aspx?
Put this code in e.g. logout.aspx:
FormsAuthentication.SignOut()
Session.Abandon()
FormsAuthentication.RedirectToLoginPage()
HttpContext.Current.ApplicationInstance.CompleteRequest()
return
IsAuthenticated will be false in login.aspx.
Login and logout code are now separated: Single Responsibility.
In your login.aspx Page_Load method:
if (!this.IsPostBack)
{
if (HttpContext.Current.User.Identity.IsAuthenticated)
{
FormsAuthentication.SignOut();
Response.Redirect(Request.RawUrl);
}
}
Update
I got comments that my answer didn't work with many folks. I wrote this answer back in 2011 after tearing my hear. So I am pretty sure it solved the problem.
I started to research this 6 years old problem and came to this solution which I believe might be the proper way of deleting the cookies which is by creating them again but with expired dates.
This works for me
public virtual ActionResult LogOff()
{
FormsAuthentication.SignOut();
foreach (var cookie in Response.Cookies.AllKeys)
{
Response.Cookies.Remove(cookie);
}
return RedirectToAction(MVC.Home.Index());
}