I’ve been reached out by one of my readers with a list of questions about AspNet Identity. First I thought the questions will be easy and I’ll wing them, but turned out that every single question in the list is worth of a separate blog post. So I’ll do a mini-series of Q-A posts about Identity framework and related stuff.
First question is about security token in a Cookie and how it is computed: Identity Framework creates a token in the cookie, token containing the same information (User.Id, Security Stamp, etc.); if the same user loggen-in in Chrome and Firefox, why are the cookies different?
I did think about it for a while, I guessed that cookie creation and expiration is encoded in the cookie, along with some sort of signature of the cookie. My guess was not far from the real world.
Fortunately, the code that deals with cookies is in Katana Project and is open-sourced.
Here is the pipeline how cookie is created on user sign-in:
- Identity framework creates
ClaimsPrincipalobject from the record in your database (that is represented by
- Identity adds list of default claims like
SecurityStampto the claims on the principal.
ClaimsPrincipalis passed to OWIN middleware: CookieAuthenticationHandler
- Authentication Handler is doing a lot of checking for different things, like should the cookie be marked as secure or persistent, sets the expiry date and many other things. Result of these checks is AuthenticationTicket which has
ClaimsIdentitywith list of claims and AuthenticationProperties which is a dictionary with load of data like cookie issue date, expiry date, is cookie persistent, etc.
- Auth ticket and claims principal is then passed down to SecureDataFormat class where data is serialised, encrypted and Base64 encoded.
The last step contains a lot of movements, let’s look deeper into it.
Authentication ticket is serialised via TicketSerializer. There
ClaimsIdentity is written into memory stream: some properties and list of the claims. Then
AuthenticationProperties (with cookie set, expiry dates) is also written to memory stream. Then this memory stream is GZipped and returned for further processing.
Next step in the pipeline is encryption. Encryption is borrowed from .Net class
DpapiDataProtector. You can read documentation on MSDN. I’m not sure about the strength of the encryption. The documentation says that
purpose parameters are effectively a list of passwords. And nowhere I’ve seen in OWIN where you can set your own encryption password and I can see that the main password is set to “Microsoft.Owin.Security.IDataProtector”. So my guess would be that no secure information should go into cookie, i.e. don’t put your connection strings into user claims!
After the encryption, stream of bytes is Base64-encoded to be transferable over the wire. And finally prepared to be set as a cookie header on HTTP Response.
Overall the process will look like this great drawing:
Anyway, the answer to the original question why the cookies are different in different browsers would be as follows: because part of the signature contains cookie creation and expiry dates, these would be different in different browsers. So data encrypted in cookie turns out to be different, the value of the cookie will be different.