Saturday, February 6, 2016

Encrypt Cookie Data ASP.Net

Please excuse my absence from writing in the blog. As usual, I got tied up in a large project that stole my focus. This is what happens to me... I get consumed by large projects and end up "going dark" for a while. No blog posts or Tweets. My family can't even get hold of me sometimes! I'm back (for now) and ready to add some more posts.

I wrote an application that uses cookies between two sites on the same domain but different sub domains. I wanted to encrypt the data stored in the cookie so that it can't be tampered with. You should never use your own encryption code to do such a thing! Seriously... Never! No matter how smart you are, there's always someone smarter... waiting... to find stuff they can hack. Do everyone a favor and use the built in encryption methods and always strive to use the highest encryption levels available to your application at the time.

My application was written in ASP.Net 3.5 due to server limitations at the time and so some of the newer encryption methods were not available to me. I found this clever solution to encrypt my cookie data string and used it.

///create your object's class
public class UserInfo
        public int AccountNumber { get; set; }
        public string FirstName { get; set; }
 public string LastName { get; set; }
 public DateTime? BirthDate { get; set; }

//populate object's info from database/web service etc
UserInfo userInfo = new UserInfo();
//your own code here to set the details

// Serialize the object's info into one long string
string cookieData = new JavaScriptSerializer().Serialize(userInfo);

//create an authentication cookie ticket, encrypt the serialized string, and create the secure cookie (for SSL)
FormsAuthenticationTicket _ticket = new FormsAuthenticationTicket(1, cookieName, DateTime.Now, DateTime.Now.AddMinutes(cookieTimeOut), false, cookieData);

string _encryptedTicket = FormsAuthentication.Encrypt(_ticket);
Cookie = new HttpCookie(cookieName, _encryptedTicket);
 Cookie.HttpOnly = true;
 Cookie.Domain = "";
 Cookie.Secure = true;                   

This code works fine if you are within the same domain, but my apps were on two different sub domains. The servers were different OSs and the applications themselves were different versions of .Net - one was ASP.Net 3.5 and the other was ASP.Net 4.0 which apparently encrypt and decrypt data completely differently and so even though my cookie was encrypted in the 3.5 app, the 4.0 app couldn't decrypt it.

You have to use a common machine key between the applications. That's understandable, but when apps are different .Net versions you also have to tell the machine key which Framework to use so that if you encrypt cookies, your apps are speaking at the same level. Use the compatibilityMode attribute on the machine key node in your web config to set this value on both your web applications. Below is the example. I had to use Framework20SP2 since one of my apps was 3.5. See Microsoft's article for additional frameworks.

<machineKey validationKey="NumbersHere" decryptionKey="MoreNumbersHere" validation="EncyrptionMethodHere (i.e. AES, SHA1, HMACSHA256, etc.)" decryption="DecryptionMethodHere (i.e. AES, DES, Auto, etc.)" compatibilityMode="Framework20SP2" />

Voila! Success encrypting a cookie between sites on sub domains with differing versions of ASP.Net.