How do I handle ValidateAntiForgeryToken across linux servers
Asked Answered
V

2

10

I have deployed an asp.net core app on some load balanced linux servers. I getting an error when POSTing a form to a route due to a failing ValidateAntiForgeryToken attribute (if a POST does not go back to the same machine as the one that generated my form).

With Windows and .Net classic I know to match MachineKey attributes in my web.config or machine.config files.

So, how do I achieve the same on linux hosts and allow a token from one server to be validated on another?

Verb answered 9/5, 2017 at 3:35 Comment(0)
V
17

So Antiforgery support is added automatically when you call services.addMvc(). You can alter the basic configuration by calling services.AddAntiforgery(opts => "your options").

Under the hood, the token is protected by ASP.Net Core Data Protection library (github repo here). By default I think this is in memory, so keys generated, and then used for token protection, are not shared on a mulitple / cloud server scenario.

Solution

So to share antiforgery tokens, you can set up the Data Protection service with a shared location. The default ones that come with the data protection library are:

//File system
services.AddDataProtection()
    .PersistKeysToFileSystem(new DirectoryInfo(@"\\some\shared\directory\"));

//Registry
services.AddDataProtection()
   .PersistKeysToRegistry(Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Sample\keys"));

Then there are a couple of defaults for better shared storage included:

//redis
var redis = ConnectionMultiplexer.Connect("my-redis-url");
services.AddDataProtection()
    .PersistKeysToRedis(redis, "DataProtection-Keys");

//Azure
services.AddDataProtection()
    .PersistKeysToAzureBlobStorage(new Uri("blob-URI"));

I have also found (and used!) an option for AWS S3 storage from github thanks to a github user named CL0SeY.

Update: Amazon released their own implementation for using AWS SSM parameter store as well. Github repo here. For testing

By default, tokens have a lifetime of 90 days. This can be set when you add the service. So one way to get a simple solution for testing is to generate a key to filesystem with a long lifetime, then deploy that token to a known location on your servers. Then set up data protection from that location, but tell it 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 on when hosted on linux with the only caveat being that you shouldn't reference windows drives or locations (duh). I am not 100% sure what would happen if you tried the registry option either...

Verb answered 16/5, 2017 at 23:17 Comment(0)
F
0

For anyone using ASP.NET Core, Antiforgery is problematic on AWS when using load balancers. Antiforgery works fine as a single instance without any configuration. Besides persisting the keys to the file system, I had to set the Target Group to use sticky sessions with a server-generated cookie. Another possibility is to use the Entity Core DbContext, which will allow multiple applications to share a key.

Fascia answered 11/11, 2023 at 5:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.