Let's suppose that we have two APIs, one for UserManagement
and one for Auth
.
UserManagement API
is responsible for initial invitation email (where i need a ResetPasswordToken
because this is my current app flow) and Auth API
is responsible for password recovery (where i need a ResetPasswordToken
).
Of course, i need to specify the same machine key for both applications.
Let's also suppose that those two applications will be deployed behind a load balancer. 2 apps x 3 instances.
It is sufficient to have the same shared location for persisting keys (Redis or so) in both APIs?
services.AddDataProtection().PersistKeysToRedis(/* */);
I'm thinking that if it works for one app, multiple instances scenario, it will work for multiple apps, multiple instances scenario too.
P.S: I wasn't able to find anything about any locking mechanism (it seems that there is one just looking at how it behaves)
Another thing that i'm concerned of: race condition?!
Duc_Thuan_Nguy Jun 9, 2017
Out of curiosity, how does key rolling handle concurrency? For example, let's say we have a web-farm with 2 machines and a shared network directory. There may be a race condition in which both machines want to roll a new key at the same time. How is this situation handled? Or the two machines can roll their own new keys and as long as they can have access to both new keys, they can unprotect data smoothly?
Comment reference: https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/implementation/key-management
Later edit: It looks like if you have multiple apps it isn't sufficient to specify that you want to persist keys in the same location. There is a concept of application discriminator (all apps being isolated).
You will need something like the following:
services.AddDataProtection(configure => {
configure.ApplicationDiscriminator = "App.X";
}).PersistKeysToRedis(/* */);
Locking and race condition questions are still valid.
The Microsoft.AspNetCore.DataProtection.Redis package allows storing data protection keys in a Redis cache. Keys can be shared across several instances of a web app. Apps can share authentication cookies or CSRF protection across multiple servers.
By default, the Data Protection system isolates apps from one another based on their content rootpaths, even if they're sharing the same physical key repository. This prevents the apps from understanding each other's protected payloads.
To share the keys among apps the key storage should be accessible to every app. e.g. Redis Server, Database Server, Azure Blob, or even a file system. You can see here some key storages available on ASP.NET Core distribution. By default, keys are generated with a 90 days validation period since the activation date.
I wrote this article some time ago, Machine Keys on an Azure App Service, machineKey multiple instances Azure, which describes how and why there are no problems running on multiple instances of your App Service Plan, so long as they are in the same region or datacenter.
No, it's not sufficient. ASP.NET Core's data protection isolates applications by default based on file paths, or IIS hosting information, so multiple apps can share a single keyring, but still not be able to read each other's data.
As the docs state
By default, the Data Protection system isolates apps from one another, even if they're sharing the same physical key repository. This prevents the apps from understanding each other's protected payloads. To share protected payloads between two apps, use SetApplicationName with the same value for each app
public void ConfigureServices(IServiceCollection services)
{
services.AddDataProtection()
.SetApplicationName("shared app name");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With