I'm running MVC 6 (vNext) in a webfarm scenario (ARR front-end with multiple AppServers). Server affinity is off.
When I bounce between app servers from one request to another I get the error
CryptographicException: The key {3275ccad-973d-43ca-930f-fbac4d276640} was not found in the key ring.
InvalidOperationException: The antiforgery token could not be decrypted.
Previously, I believe this was handled by setting a static MachineKey in the web.config.
As I understand it, we've now moved to a new DataProtection API and I've tried the following, thinking the application name is used as some kind of seed:
services.AddDataProtection();
services.ConfigureDataProtection(configure =>
{
configure.SetApplicationName("WebAppName");
});
which does not work to solve the problem.
Any idea how to solve this issue in vNext?
Explanation
You'll need to reuse the same key.
If you are on Azure, the keys are synced by NAS-type storage on %HOME%\ASP.NET\DataProtection-Keys
.
For locally run application, they are stored in the %LOCALAPPDATA%\ASP.NET\DataProtection-Keys
of the user running the application or stored in the registry if it's being executed in IIS.
If none of the above match, the key is generated for the lifetime of the process.
Solution
So the first option is not available (Azure only). However, you could sync the keys from %LOCALAPPDATA%\ASP.NET\DataProtection-Keys
of the user running your application on each machine running your application.
But even better, you could just point it to a network share like this:
sc.ConfigureDataProtection(configure =>
{
// persist keys to a specific directory
configure.PersistKeysToFileSystem(new DirectoryInfo(@"Z:\temp-keys\"));
});
This will allow you to scale while keeping your security.
Important: Your keys will expire every 90 days. It will be important to regenerate them frequently.
You can change it using this bit of code but the shorter, the safer you are.
services.ConfigureDataProtection(configure =>
{
// use 14-day lifetime instead of 90-day lifetime
configure.SetDefaultKeyLifetime(TimeSpan.FromDays(14));
});
Source
- Key Encryption at Rest
- Default Settings