R – Storing custom user information in an authentication ticket instead of in Membership provider

cookiesforms-authenticationmembershiprolessession

I've been looking at implementing a custom SQL Server-based membership provider and one of my problems is that the membershipUserObject is keyed on a GUID. Since I'm using an existing ID as a key to roles and user data, this presents an interesting problem.

I'd like your opinion on which option — or whether there's another option I haven't considered — to use if I want to persist my own ID in a web session without round-tripping to the database constantly. I know that, by default, the login control creates a Forms Authentication cookie with the username of the membership object. So — I could:

  1. Implement the Logging_In method of the login control to add my field to the authentication cookie manually

if (Membership.ValidateUser(Login1.UserName, Login1.Password))
{
FormsAuthenticationTicket ticket = new
FormsAuthenticationTicket(
1,
Login1.UserName,
DateTime.Now,
DateTime.Now.AddMinutes(30),
Login1.RememberMeSet,

"some custom data want to store in ticket….", // User-data,
in this case the roles
FormsAuthentication.FormsCookiePath);

string hash = FormsAuthentication.Encrypt(ticket);
HttpCookie cookie = new HttpCookie(
FormsAuthentication.FormsCookieName,
hash);

if (ticket.IsPersistent) cookie.Expires = ticket.Expiration;

Response.Cookies.Add(cookie);

  1. Create a custom MembershipUser Object that inherits from MembershipUser and provides my extra property. I'll still have to persist it somehow (in Session? eww..)

  2. Create a custom Profile Provider that contains the extra field and cache that in session. This seems a bit like overkill, though, for the few fields I would actually cache.

What's the best practice here? I've read countless articles and the extra data in the forms ticket seems like the best so far.

Best Answer

The MembershipUser.ProviderUserKey is of type object, using the default provider we cast this to a Guid in order to use it.

Since you are using a custom membership provider, when you retrieve a user from the database couldn't you populate MembershipUser.ProviderUserKey with an int (or whatever type your id is)? Of course, you would have to cast MembershipUser.ProviderUserKey to an int every time you wanted to use it.