RCF 2109 - HTTP State Management Mechanism - provides the standard for how browsers should handle cookies. Near the end of the RFC, the following recommendation is made:
Practical user agent implementations have limits on the number and size of cookies that they can store. In general, user agents' cookie support should have no fixed limits. They should strive to store as many frequently-used cookies as possible. Furthermore, general-use user agents should provide each of the following minimum capabilities individually, although not necessarily simultaneously:
- at least 300 cookies
- at least 4096 bytes per cookie (as measured by the size of the characters that comprise the cookie non-terminal in the syntax description of the Set-Cookie header)
- at least 20 cookies per unique host or domain name
On KB article 306070, Number and Size Limits of a Cookie in Internet Explorer, Microsoft states that they “comply” with the RFC by providing the bare minimum cookie requirements. Urm, hello, Microsoft... these are the minimum capabilities. Perhaps the goal here was not to have to have different cookie-handling code for IE based on the device (for example, a hand held device or cell phone might need to place such size/length restrictions on cookies), but it seems a bit annoying that such limitations should be placed on IE 6 when being used on my desktop, which has dozens of gigabytes just waiting to hold cookie data. (There is a workaround for the 20 cookie limit - namely, use a cookie dictionary. See the KB article for more info.)
Anyway, this 20 cookie limit came to bite me in the behind. The scenario: a website using forms-based authentication and a Web page using Telerik's r.a.d. spell control. Each r.a.d. spell control on a site emits a session-based cookie for the purpose of 'securing the dialog.' I'm not 100% clear what that means or what, exactly, is being secured. Initially I assumed that it had something to do with the client-side spell checking dialog, ensuring that some cross-site script or some other attack couldn't be used to read or modify the contents while being spelled checked. That was my guess, at least, until I found that there's a UseSession property that will store whatever is needed to ensure the 'security' in a session variable. Hrm, so it's a server-side check... I'm confused, but I digress.
Anywho, the UseSession property is False by default, so by default each time a user visits a page that has a spell checker control, or visits a page with many spell checker controls, new cookies get added to the browser. You can probably see where I'm heading with this - one particular page had over 40 spell checking control instances on it which proceeded to write 40+ cookies to the client. Since IE can only remember 20, it conveniently decided to nix my forms-based authentication ticket cookie. The end result? Whenever I visited this page, after posting back I'd immediately be kicked back to the logon page because the authentication ticket was getting overwritten by the slew of r.a.d. spell cookies. Meh.
The workaround, in my case, was to simply set the UseSession property to True, thereby avoiding the plethora of r.a.d. spell cookies and thereby preserving my forms-based authentication ticket.
It took a bit of researching to figure this particular one out, and it wouldn't have been possible without Fiddler, a great tool for inspecting the incoming & outgoing HTTP streams. (I mentioned Fiddler a few weeks back in my Scott Hanselman's Recommended Tools blog entry.) Thanks to Fiddler I was able to see the mess of cookies being added by r.a.d. spell and the corresponding loss of my forms-based authentication ticket cookie. In addition, I set a breakpoint on the Global.asax's AuthenticateRequest event handler and added to the Watch window Request.IsAuthenticated. On postback, then, I would hit the breakpoint and see that I had 'lost' my authenticated status.
In any event, if you find yourself being 'automagically' logged out of your site, perhaps it may be due to using IE as your browser and having too many cookies from your domain. Hope this helps someone save the time that I invested.