Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataProtection - Share machine key between multiple applications

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.

like image 247
Razvan Dumitru Avatar asked Dec 07 '17 10:12

Razvan Dumitru


People also ask

How do I share data protection keys across multiple servers?

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.

How does data protection isolate apps from one another?

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.

How to share the keys among apps?

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.

Can machinekey run on multiple instances of an Azure App service?

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.


1 Answers

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");
}
like image 110
blowdart Avatar answered Oct 28 '22 21:10

blowdart