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

Wednesday, December 17, 2014

Generate MachineKey in IIS 7.0+

Normally machineKey is already configured in your machine.config file which is applied to all your application if you are working in the same Web Farm. But most of the time this may not be the scenario, it may be possible that your applications are distributed across different Web Farms.

To deal with this all you need is to configure the same decryption keys in web.config of all the applications to decrypt the authentication cookie created at client side.

To generate a new machine key all you need is to first open the IIS Admin Console, and

1. Select the Server

2. Select the Machine Key from right hand side of the console

image

3. Double Click to open the Machine Key and then Select ‘Generate Keys’ from Actions

image

4. You got the Decryption Key and Unique Key

You can use this Keys in you web.config file which might look similar to something like

image

Monday, December 15, 2014

UnSubscription Email Utility

In this post I am going to show a very simple yet very useful utility which everyone of us encounter when we get lots of unwanted mails which we had subscribed sometime in our web exploration but later we want to get rid of those subscribed mails. Moreover this is a very integral part of our business use cases.

I have used ASP.NET MVC as an example but if you understand the concept, this can be achieved using any of your favorite programming logic as well.

I tried to keep the example as simple as possible so that I can cover the concept/business logic in more details. In this example as soon as I run the application I will call the Index action method with my hardcoded email id. In real world you might want to make it more dynamic and will try to pass this as a parameter.

image

Now I have written a utility  method which is used to generate the subscription link, which can be embedded in the marketing emails, so when the user click on this link Say Unsubscribe Me, he will land on the page where just in a click of button his mail id will be removed from the marketing email database.

image

For the simplicity sake of this example I have not used the real time database operations but for your implementation you will definitely need DB operation to update the user preferences.

Not let me highlight the most important logic of this GetUnSubscriptionLink method; since we are dealing with one key information of a user which is his email id, so I have used CryptoHelper utility which is used to Encrypt the email id of the consumer. This will also help us to filter any Brute force attack where the hacker will try to enter random emails on his list to invoke the unsubscribe methods.

You can download your copy of CryptoHelper utility from here: http://1drv.ms/1r2kisl

One of the example of the unsubscription link is shown in the screen below. For better programming practice you can configure the root URL in your config file.

image

Additionally you can do a second level of validation where you can prompt the end user to provide his email id in a text box and validate this against the decrypted string containing the email id from the query string, if both has a match then unsubscribe otherwise ignore the unsubscribe request.

In my example as soon as you pass all the validation I am calling the Unsubscribe action method of my controller which takes the encryptedText as a parameter and decode the text to unsubscribe the user from marketing emails.

image

Sample screen once the user is unsubscribed

image

I am providing below a utility Property which I found somewhere on internet, this might be very useful to you if you are playing with URL’s

image

Crypto Helper Utility: http://1drv.ms/1r2kisl

You can download the full working copy of this example from this link: http://1drv.ms/1vU5ZCO

Hope this helps, let me know in comments if you have any trouble in downloading the files or understanding my thoughts Smile

Thursday, December 11, 2014

Hello World !!! using Apache Cordova and Visual Studio 2013

You heard it right, this is for all the .NET Developers (other platform also welcome) who have ever wished to build an app using Apache Cordova that targets multiple mobile platforms: Android, iOS, Windows, and Windows Phone.

Disclaimer: All images are copyright to their respective owners.

I am going to show you a very simple mobile application which displays Hello World, using apache Cordova and Visual Studio 2013.

1. Setup the environment by installing the Preview of Visual Studio Tooling Support for Apache Cordova, you can download the CTP from here.

Visual Studio Tools for Apache Cordova

image

2. Once the installation is complete, run Visual Studio 2013 and create a new project. You need to go to Javascript templates or you can select the Multi device Hybrid App and click OK button. this will give you default project structure

image

image

3. For this post I am not going to explain all the files, rather I will go directly to my index.html and change the default text Hello World !!! and we are done.

image

4. And finally select the desired Emulators and run the program.

image

And here is the output, that’s it and you are done.

image

You can double click on config.xml file to customize the Custom and Core properties of your application individually for each platforms.

image

Hope this makes your life simple Smile Enjoy.

Other helpful link:

http://msopentech.com/blog/2014/05/12/apache-cordova-integrated-visual-studio/

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