Azure AD, ASP.NET Core Web App, and Service Fabric: How to get auth working on multiple machines?

笑着哭i 提交于 2019-12-13 20:15:14

问题


I have an ASP.NET Core Web App, and I want to use Azure AD authentication. I've got it all set up and working locally, but when I deploy it to my Service Fabric instance, I'm getting errors on internal API calls, because it attempts to login again on the API call.

After some digging, I discovered that by default, the Machine Key is used to encrypt the cookie. My SF instance has multiple machines running, which seems to be the culprit (different machines cannot read the same cookie, therefore, thinks I am not authenticated).

Is there a way to get the AAD cookie authentication to use the same key between machines?

This is what I currently have in my ConfigureServices call:

services.AddDataProtection()
    .SetApplicationName("my-app")
    .ProtectKeysWithCertificate("my-thumbprint")
    .PersistKeysToFileSystem(new DirectoryInfo("dp-keys"));

But this still doesn't seem to work - a different key is still generated on each machine. At the moment, I don't have a way to share a file between all the machines - would that be the only solution, or would there be something else as well?


回答1:


Since we are on service fabric, you properly already have a cert deployed that your cluster can use. Otherwise you would have to add a certificate.

Then you can do the following:

var cert = X509.LocalMachine.My.Thumbprint.Find("C03BB5A6410741CDD2927B4FF88C3E67215A393B", validOnly: false).FirstOrDefault();
services.AddApplicationStorageDataProtection(_container, cert);

and

    public static IServiceCollection AddApplicationStorageDataProtection(this IServiceCollection services, IUnityContainer container, X509Certificate2 cert )
    {
        if (container != null)
        {

            try
            {
                var storage = container.Resolve<IApplicationStorageService>();
                var token = storage.GetApplicationStorageSharedAccessSignature().GetAwaiter().GetResult();
                var name = storage.GetApplicationStorageAccountNameAsync().GetAwaiter().GetResult();
                var a = new CloudStorageAccount(new StorageCredentials(token), name, null, true);
                var c = a.CreateCloudBlobClient().GetContainerReference("dataprotection");
                c.CreateIfNotExists();

                services.AddDataProtection()
                 .ProtectKeysWithCertificate(cert)
                 .PersistKeysToAzureBlobStorage(c.GetBlockBlobReference("dummy.csrf"));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
                throw;
            }
        }

        return services;
    }

You would of cause have to change the code to your needs. The code provided here is using a deployed storage service in the cluster, such I dont need to manage credentials for storage in all my applications, but simply can ask the storage service for the credentials, and also the unity container is just there because this is the underlying DI framework that i am using.

So the part that you need is:

 services.AddDataProtection()
                 .ProtectKeysWithCertificate(cert)
                 .PersistKeysToAzureBlobStorage(c.GetBlockBlobReference("dummy.csrf"));



回答2:


In a web farm scenario you need to use a shared secret across the servers to protect the cookie. This P&P link explains it in more detail.

By default, when you use the Windows Identity Foundation (WIF) framework to manage your identity infrastructure, it encrypts the contents of the cookies that it sends to the client by using the Windows Data Protection API (DPAPI). Using DPAPI for cookie encryption is not a workable solution for an application that has multiple role instances because each role instance will use a different encryption key, and the Windows Azure load balancer could route a request to any instance. You must use an encryption mechanism such as RSA, which uses a key that two or more instances can share.

It's resolved there by using a certificate for encryption.

new RsaEncryptionCookieTransform(e.ServiceConfiguration.ServiceCertificate)


来源:https://stackoverflow.com/questions/45470506/azure-ad-asp-net-core-web-app-and-service-fabric-how-to-get-auth-working-on-m

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!