Manual Sign Out in ASP.NET Forms Authentication
July 28, 2008 at 10:03 AM
Recently I have been developing numerous applications in ASP.NET and Flex Builder 3. For security I utilized forms authentication as provided by ASP.NET engine. At first, everything worked well until there was a need to manually sign out current user. Quick look into MSDN documentation revealed SignOut() method of FormsAuthentication class. The documentation promised that this method signs out the user and redirects the client to login page. Considering the fact that I did not care about redirect (Flex application was running on the client side, so that redirection did not have any effect), I was hoping that the method would still perform desired effect and "de-authenticate" (I know, I know, that is not even a word) current user. At first, it seemed to work, but debugging revealed that even though this method removed authentication cookie, it did not sign out the user. User's identity was still marked as authenticated and subsequent calls to the Http handler would be considered authenticated. Furthermore, the session object was still valid, so that existing session information was still available. Quick look into MSDN revealed Session.Abandon() method, which would destroy session object upon execution. However, even though the session object was destroyed, client calls to ASP.NET web application were still considered authenticated. It was time to search the web to see if other developers faced the same issue.
After some research I ran into following Microsoft article: http://support.microsoft.com/kb/900111. The article explains that FormsAuthentication.SignOut() method does not prevent cookie reply attack, which essentially means that the cookie, even though it was destroyed, it was considered to be valid and all calls to the application that utilized this particular cookie were considered authenticated. The same article presented some possible workarounds, but it did not satisfy my needs. It bugged me that in order to prevent the access to secure parts of the application (even after log off), I had to track the security on client side (in addition to server side). So I tried following code:
/* Create new session ticket that expires immediately */
FormsAuthenticationTicket ticket =
/* Encrypt the ticket */
string encrypted_ticket = FormsAuthentication.Encrypt(ticket);
/* Create cookie */
HttpCookie cookie = new HttpCookie(
/* Add cookie */
/* Abandon session object to destroy all session variables */
Essentially the code replaces old cookie with new security cookie that expires immediately, which performs user sign out. In addition, all session variables are destroyed and new session is created so that old session cannot be reused. However, it is essential to mention that the technique presented in this post does not prevent Cookie Reply Attack. The old cookie is still valid for the duration specified in FormsAuthenticationTicket constructor.