Monday, December 22, 2014

Sharing the Cookies in Web Farm OR across different servers

Consider you have an application which provides you an authentication cookie using ASP.NET Membership provider, and you are using this authentication cookie across multiple servers to access the secured contents. I have depicted this scenario using the diagram below.

image

Now to read the client cookies across the applications you can simple use the following line of line of code fetch the cookies

HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value;

But wait a minute, is it that simple? In fact yes except the fact that to secure your session and prevent from any men in the middle attacks your cookies are encrypted using the machine key of Authentication Server. Which might look similar to the one below. This is configured at your machine level, which means you may not usually find this key in your local web.config files.

<machineKey  
  validationKey="21F090935F6E49C2C797F69BBAAD8402ABD2EE0B667A8B44EA7DD4374267A75D7AD972A119482D15A4127461DB1DC347C1A63AE5F1CCFAACFF1B72A7F0A281B" 
  decryptionKey="ABAA84D7EC4BB56D75D217CECFFB9628809BDB8BF91CFCD64568A145BE59719F" 
  validation="SHA1" decryption="AES"/>

And also you might be aware that every machine has its own machine.config file which is tailored to that particular machine, so if the cookie is encrypted using the machine key of Server1 then it cannot be decrypted using machine key of Server2 or any other Server.

So even if you managed to get the cookie, but when you try to read the data from the cookie you must have to first decrypt the cookie in order to read any key from the cookie. I have provided below a sample code which exactly does the same.

private void SetFormsAuthenticationTicket()
{
    FormsAuthenticationTicket ticket = default(FormsAuthenticationTicket);
    if (System.Web.HttpContext.Current.Request.Cookies.Get(System.Web.Security.FormsAuthentication.FormsCookieName) != null)
    {
        ticket = System.Web.Security.FormsAuthentication.Decrypt(
            System.Web.HttpContext.Current.Request.Cookies.Get(
            System.Web.Security.FormsAuthentication.FormsCookieName).Value);
        string[] roles = ticket.UserData.Split(new char[] { '|' });
        GenericIdentity userIdentity = new GenericIdentity(ticket.Name);
        GenericPrincipal userPrincipal = new GenericPrincipal(userIdentity, roles);
        System.Web.HttpContext.Current.User = userPrincipal;
    }
}

To get a better view I have also provided the screenshot of the code below.

image

This does solve your problem, but the when you try run the code you might get the following exception.

System.Web.HttpException : Unable to validate data. at System.Web.Configuration.MachineKeySection.EncryptOrDecryptData(Boolean fEncrypt, Byte[] buf, Byte[] modifier, Int32 start, Int32 length, IVType ivType, Boolean useValidationSymAlgo, Boolean signData)

image

This happens because as I mentioned above, your cookie was created by machine key of Server1, but some of the part of your application is served by Server2 which tries to decrypt the cookie using the code above. So to mitigate this issue first this you might need to do is to generate the machineKey which can be shared across all your applications who is sharing the cookies and located across your network. I have written a separate post on How to generate  the machineKey using IIS 7.0+ you can visit the link: http://www.dotnetglobe.com/2014/12/generate-machinekey-in-iis-70.html

Secondly you have to place the same decryptionKey in all your application local web.config, and you are done.

You might encounter this types of scenario is small scale applications, but for most of the complicated application these days where applications are placed on completely different domains, you will need to implement your own SSO architecture. Details are out of then scope of this article, so you might take a look for details in some other article such as Single Sign On (SSO) for cross-domain ASP.NET applications or Single Sign-On (SSO) for .NET or Using a third party identity provider like Facebook, Google, etc

References:

http://msdn.microsoft.com/en-us/library/ff649308.aspx

http://www.codeproject.com/Articles/288631/Secure-ASP-NET-MVC-applications

0 comments:

Post a Comment