FormsAuthentication: gotcha with SignOut

Sergei Dorogin
Sergei Dorogin’s technical blog
2 min readJan 31, 2013

--

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);
}

--

--