FormsAuthentication: gotcha with SignOut
Today I encountered some gotcha of FormsAuthentication.SignOut
which I’d like to share.
I have an authentication engine in my ASP.NET Single Page Application based on ASP.NET Web API (I blogged on this before).
I have an Api-controller with Login
and Logout
methods. Login
method accepts a username/password pair from the client and sets .AUTH
cookie via FormsAuthentication
class. Logout
method removes this cookie.
public class LoginData
{
public string UserName { get; set; }
public string Password { get; set; }
}
[AllowAnonymous]
public class SecurityController : ApiController
{
public SecurityController ()
{
// get the app's root ("/" for site or "/myapp" for virtual directory)
var abstractContext = new HttpContextWrapper(HttpContext.Current);
this._root = System.Web.Mvc.UrlHelper.GenerateContentUrl("~", abstractContext );
}
[AllowAnonymous]
[HttpPost]
public DomainResult LoginFormsAuth(LoginData login)
{
// here some authentication process
setAuthTicket(login.UserName);
}
protected virtual void setAuthTicket(string userName)
{
FormsAuthentication.SetAuthCookie(userName, true, this._root);
}
[HttpPost]
[HttpGet]
public void Logout()
{
FormsAuthentication.SignOut();
}
}
As I want my auth cookie to be ‘per application’ I specify a path on the cookie creation (see the last parameter for FormsAuthentication.SetAuthCookie
in setAuthTicket
method).
After Login
was called the browser gets something like this from the server:
Set-Cookie:.ASPXAUTH=C9...6; expires=Fri, 31-Jan-2014 15:48:19 GMT; path=/myapp/; HttpOnly
For logging out the client calls Logout
method of SecurityController
: POST http://localhost/ajax/api/_security/logout?tm=1359647293724
And as result the browser gets:
Set-Cookie:.ASPXAUTH=; expires=Mon, 11-Oct-1999 19:00:00 GMT; path=/; HttpOnly
Can you see the problem? path’s value differs from the one in Login’s cookie(“/myapp”). So the browser continues to use original cookie (acquired from Login).
The problem is that FormsAuthentication.SignOut
method can’t accept path argument and unconditionally uses value from web.config (FormsAuthentication.FormsCookiePath
).
Here’s how to fix:
protected virtual void removeAuthTicket()
{
// NOTE: FormsAuthentication.SignOut() cannot be used as it doesn't allow specify cookie' path
HttpCookie cookie = FormsAuthentication.GetAuthCookie(null, true, Config.Root);
cookie.Expires = new DateTime(1999, 10, 12);
HttpContext current = HttpContext.Current;
current.Response.Cookies.Add(cookie);
}