1. Tatham Oddie
  2. FormsAuthenticationExtensions

Overview

How to get it

Only installable via NuGet: Install-Package FormsAuthenticationExtensions

(You all use NuGet by now, right?)

What it does

Think about a common user table. You probably have a GUID for each user, but you want to show their full name and maybe their email address in the header of each page. This commonly ends up being an extra DB hit (albeit hopefully cached).

There is a better way though! A little known gem of the forms authentication infrastructure in .NET is that it lets you embed your own arbitrary data in the ticket. Unfortunately, setting this is quite hard - upwards of 15 lines of rather undiscoverable code.

Using this library though, all you need to do is change:

FormsAuthentication.SetAuthCookie(user.UserId, true);

to:

var ticketData = new NameValueCollection
{
    { "name", user.FullName },
    { "emailAddress", user.EmailAddress }
};
new FormsAuthentication().SetAuthCookie(user.UserId, true, ticketData);

Those values will now be encoded and persisted into the authentication ticket itself. No need to store it in any form of session state, custom cookies or extra DB calls.

To read the data out at a later time:

var ticketData = ((FormsIdentity)User.Identity).Ticket.GetStructuredUserData();
var name = ticketData["name"];
var emailAddress = ticketData["emailAddress"];

If you want something even simpler, you can also just pass a string in:

new FormsAuthentication().SetAuthCookie(user.UserId, true, "arbitrary string here");

and read it back via:

var userData = ((FormsIdentity)User.Identity).Ticket.UserData;

Things to consider

Any information you store this way will live for as long as the ticket.

That can be quite a while if users are active on your application for long periods of time, or if you give out long-term persistent sessions.

Whenever one of the values stored in the ticket needs to change, all you need to do is call SetAuthCookie again with the new data and the cookie will be updated accordingly. In our user name / email address example, this is actually quite advantageous. If the user was to update their display name or email address, we'd just update the ticket with new values. This updated ticket would then be supplied for future requests. In web farm environments this is about as perfect as it gets - we don't need to go back to the DB to load this information for each request, yet we don't need to worry about invalidating the cache across machines. (Any form of shared cache in a web farm is usually a bad move.)

Size always matters.

The information you store this way is embedded in the forms ticket, which is then encrypted and sent back to the users browser. On every single request after this, that entire cookie gets sent back up the wire and decrypted. Storing any significant amount of data here is obviously going to be an issue. Keep it to absolutely no more than a few simple values.