How to handle ValidateAntiForgeryToken via linux servers
I have deployed a main asp.net application on some balanced Linux servers. I am getting an error when submitting a form to a route due to an attribute failure ValidateAntiForgeryToken
(unless the POST is returned to the same computer as the one that generated my form).
With Windows and .Net classic, I know to match attributes MachineKey
in my files web.config
or machine.config
.
So how do I achieve the same on linux hosts and allow token validation from one server to another?
So Antiforgery support is added automatically when you call services.addMvc()
. You can change the basic configuration by calling services.AddAntiforgery(opts => "your options")
.
Under the hood, the token is protected by the ASP.Net Core Data Protection library (github repo here ). By default, I think it is in memory, so the keys generated and then used to protect against tokens are not used in a multi or cloud server scenario.
Decision
So, to share anti-corrosion tokens, you can set up a data protection service with a shared location. The default for the data protection library is:
//File system
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\\some\shared\directory\"));
//Registry
services.AddDataProtection()
.PersistKeysToRegistry(Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Sample\keys"));
Then there are a few defaults for the best shared storage:
//redis
var redis = ConnectionMultiplexer.Connect("my-redis-url");
services.AddDataProtection()
.PersistKeysToRedis(redis, "DataProtection-Keys");
//Azure
services.AddDataProtection()
.PersistKeysToAzureBlobStorage(new Uri("blob-URI"));
I also found (and is using!) An option to store AWS S3 from GitHub thanks to a GitHub user named CL0SeY .
For testing
By default, tokens have a duration of 90 days. This can be set when adding a service. Thus, one way to get a simple test solution is to create a key for a long-lived filesystem and then deploy that token to a known location on your servers. Then set up data protection from that location, but tell him to never generate new keys:
//generate a test key with this in a test app or whatever:
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"c:\temp\"))
.SetDefaultKeyLifetime(TimeSpan.MaxValue);
// then use that key in your app:
services.AddDataProtection()
.PersistKeysToFileSystem(new DirectoryInfo(@"\some\allowed\directory"))
.DisableAutomaticKeyGeneration();
On linux
All of this should work when hosted on Linux with one caveat, as you must not reference Windows drives or locations (duh). I'm not 100% sure what happens if you try the registry setting ...