Most cryptography related features of the ASP.NET platform relies on the machine key, therefore it is very important to assign unique machine keys to independent applications. Thankfully the default configuration looks like ensuring this both for the validation key and the decryption key:
The AutoGenerate option frees you from manually setting the keys, and the IsolateApps options ensures that unique keys are generated for every application.
But not always!
ASP.NET will definitely generate a key, but it is neither the validation key, nor the decryption key, but instead a base key (let’s call it the machine key), which is then transformed into the validation key and the decryption key. The base machine key is stored in the registry in the following location:
Note that this key sits in the HKEY_CURRENT_USER hive, so the generated machine key belongs to the user’s that runs the application profile. This means that if you have two applications in IIS which are running with the same process identity, they will use the same machine key! One more reason why you should forget the SYSTEM, LOCAL SERVICE and NETWORK SERVICE accounts, and run all your web applications with separate ApplicationPoolIdentity. This also shows that the application pool is the real app isolation boundary.
Having two applications that share the same base key is not necessary a problem, because the keys used to validate and encrypt are created with additional transformations from this key. This transformation is determined by the second modifier after AutoGenerate. If you set IsolateApps, the runtime will use the value of the HttpRuntime.AppDomainAppVirtualPath property, which is different for two applications sitting in different virtual directories on the same website, so the generated keys will be different (which is good).
On the other hand, if you have two applications in the same path but on different websites, the value of this property will be the same for both apps. For example for an app that sits in the site root, the value is “/”, so IsolateApps does not provide you the isolation you expect!
To solve this problem ASP.NET 4.5 introduced a new modifier called IsolateByAppId, which uses the HttpRuntime.AppDomainAppId property instead of the AppDomainAppVirtualPath. The value of this property is something like this:
The “3” in the middle is the ID of the site in my case, and “ROOT” means that the app sits in the site root.
To summarize: the default AutoGenerate,IsolateApps setting does not necessarily provides you with unique keys, but if you host your apps in their own application pools which are running with ApplicationPoolIdentity, and you use IsolateByAppId instead of IsolateApps you can be sure, that your apps will use unique autogenerated keys.
The simplest way to test these setting is to use the localtest.me domain to create two separate websites, and then create a simple webpage that uses Milan Negovan’s code to retrieve and display the autogenerated keys.