Extensions: KeyVault 2.2 nuget: Could not load file or assembly 'Microsoft.IdentityModel.Clients.ActiveDirectory.Platform'

Created on 17 May 2019  路  21Comments  路  Source: dotnet/extensions

Describe the bug

I utilize one library that requires Microsoft.IdentityModel.Clients.ActiveDirectory >= 4.5.0, however starting with version >= 4 of that library, the dependency namespace 'Microsoft.IdentityModel.Clients.ActiveDirectory.Platform' is no longer listed.

The Microsoft.Extensions.Configuration.AzureKeyVault v2.2.0 nuget package requires Microsoft.IdentityModel.Clients.ActiveDirectory >= 3.14.x which does have the required dependency namespace 'Microsoft.IdentityModel.Clients.ActiveDirectory.Platform'

Microsoft.Extensions.Configuration.AzureKeyVault v2.2.0 crashes on not finding the 'Microsoft.IdentityModel.Clients.ActiveDirectory.Platform' dependency because in my solution I am using Microsoft.IdentityModel.Clients.ActiveDirectory v4.5.0.

I cannot downgrade Microsoft.IdentityModel.Clients.ActiveDirectory to 3.19.8 as alot of posts have suggested because my other dependency requires >= 4.5.0.

To Reproduce

Steps to reproduce the behavior:

  1. Use version '2.2.0' of package 'Microsoft.Extensions.Configuration.AzureKeyVault'
  2. Use version '4.4.3' of package 'Microsoft.Bot.Builder'
  3. Run this StatelessService code in a .net core project:
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
    return new ServiceInstanceListener[]
    {
        new ServiceInstanceListener(serviceContext =>
            new KestrelCommunicationListener(serviceContext, "ServiceEndpoint", (url, listener) =>
            {
                ServiceEventSource.Current.ServiceMessage(serviceContext, $"Starting Kestrel on {url}");
                return WebHost.CreateDefaultBuilder()
                    .ConfigureAppConfiguration((context, config) =>
                    {
                            var keyVaultName = "<KEYVAULT NAME>";
                            var azureServiceTokenProvider = new AzureServiceTokenProvider();
                            var keyVaultClient = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(azureServiceTokenProvider.KeyVaultTokenCallback));
                            config.AddAzureKeyVault(keyVaultName, keyVaultClient, new DefaultKeyVaultSecretManager());
                    })
                    .ConfigureServices(
                        services => services
                            .AddSingleton<StatelessServiceContext>(serviceContext))
                    .UseStartup<Startup>()
                    .UseServiceFabricIntegration(listener, ServiceFabricIntegrationOptions.None)
                    .UseUrls(url)
                    .Build();
            })),
    };
}

Expected behavior

Service starts up and runs.

Failing behavior is that FileNotFoundException is thrown with error Could not load file or assembly 'Microsoft.IdentityModel.Clients.ActiveDirectory.Platform'

Additional context

Add any other context about the problem here.

$ dotnet --info
Zestaw .NET Core SDK (odzwierciedlenie dowolnego pliku global.json):
 Version:   2.2.106
 Commit:    aa79b139a8

Srodowisko uruchomieniowe:
 OS Name:     Windows
 OS Version:  10.0.17763
 OS Platform: Windows
 RID:         win10-x64
 Base Path:   C:\Program Files\dotnet\sdk\2.2.106\

Host (useful for support):
  Version: 2.2.4
  Commit:  f95848e524

.NET Core SDKs installed:
  1.0.0-preview2-003131 [C:\Program Files\dotnet\sdk]
  1.0.0 [C:\Program Files\dotnet\sdk]
  1.0.4 [C:\Program Files\dotnet\sdk]
  1.1.0 [C:\Program Files\dotnet\sdk]
  2.1.101 [C:\Program Files\dotnet\sdk]
  2.1.202 [C:\Program Files\dotnet\sdk]
  2.1.402 [C:\Program Files\dotnet\sdk]
  2.1.403 [C:\Program Files\dotnet\sdk]
  2.1.500 [C:\Program Files\dotnet\sdk]
  2.1.502 [C:\Program Files\dotnet\sdk]
  2.1.505 [C:\Program Files\dotnet\sdk]
  2.2.106 [C:\Program Files\dotnet\sdk]

.NET Core runtimes installed:
  Microsoft.AspNetCore.All 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.All 2.2.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
  Microsoft.AspNetCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 2.2.4 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 1.0.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.0.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.1 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 1.1.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.0.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.5 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.6 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.1.9 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
  Microsoft.NETCore.App 2.2.4 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
area-config

Most helpful comment

I don't think that's an option for me as I'm running on dotnet core 3.1 and the 3.14.2 DLL isn't compatible with that from what I understand.

Moreover, I'm interested in a response from the ASPNet team on the proper fix for this.

All 21 comments

Seems to be caused by this issue: https://github.com/Azure/azure-sdk-for-net/issues/5788

Once that is resolved and published, this solution should update the version as well

Any update on this issue? AppAuthentication v1.3.0 was released a few weeks ago and bumps the ADAL dependency to >= 4.3.0, though the related issue hasn't yet been marked as closed.

@MattSFT
This is still an issue even with using AppAuth v1.3.0. Regardless of which version of AppAuth I use, Microsoft.Extensions.Configuration.AzureKeyVault requires Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll to exist. In fact, for my app using cert auth into keyvault, AppAuth isn't even being used and the reference to Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll seems to be directly from AzureKeyVault. I was able to get my app to work by manually including the missing dll, without having to reference AppAuth at all. Seems like this is an issue that needs to be fixed with AzureKeyVault as it has an implicit dependency on Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll and one that is outdated as the dll is no longer packaged in later versions. If any other dependency requires higher version of ActiveDirectory, then you will be unable to run your app without manually referencing a downloaded Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll.

My code usage:

        return WebHost.CreateDefaultBuilder(args)
           .UseSetting(WebHostDefaults.DetailedErrorsKey, "true")
           .ConfigureAppConfiguration((context, builder) =>
           {
               builder.AddDMServiceConfiguration(context);
               var builtConfig = builder.Build();
               using (var store = new X509Store(StoreName.My,StoreLocation.CurrentUser))
               {
                   store.Open(OpenFlags.ReadOnly);
                   var certs = store.Certificates
                       .Find(X509FindType.FindByThumbprint, builtConfig["ApplicationIdentity:CertThumbprint"], false);

                   builder.AddAzureKeyVault(
                       $"https://{builtConfig["KeyVault:Name"]}.vault.azure.net/",
                       builtConfig["ApplicationIdentity:AppId"],
                       certs.OfType<X509Certificate2>().Single());

                   store.Close();
               }
           })
           .ConfigureServices((context, serviceCollection) =>
           {
               serviceCollection.AddDMLogging(context);
           });

@Mdub28 Found your comment while searching for a solution to this very issue. Thanks a lot for the workaround... I hope MSFT is able to resolve this soon.

I have the same issue on a bot builder 4 projet, it works fine on my vanilla WebApi project, is this help?

Any updates on this? I'm also experiencing this issue.

@ajcvickers - you were the last one to update Microsoft.Azure.Services.AppAuthentication with PR #505: Update version for Azure Services App Authentication.

Any chance you can update it further to 1.3.1 which no longer has the dependency on outdated version 3.14.2 of Microsoft.IdentityModel.Clients.ActiveDirectory?

We worked around the issue by downloading the old 3.14.2 DLL and referencing it directly (although we wrapped it into a NuGet package rather than checking the DLL directly into source control)

I don't think that's an option for me as I'm running on dotnet core 3.1 and the 3.14.2 DLL isn't compatible with that from what I understand.

Moreover, I'm interested in a response from the ASPNet team on the proper fix for this.

@Pilchie Regarding the last few comments, is this something we should update? (I believe I only sent the PR last time while helping Nate get things working.)

@gsacavdm Thanks for letting me know about that DLL not being compatible with netcore3.1...that's likely going to cause a problem for us pretty soon.

For what its worth this is blocking my company from moving to Azure Key Vault - we are using BotBuilder as well. I've tried the workaround but haven't been able to get it to work (and it's a bit of a hack really) so I'm really hoping for a proper solution to this.

We've got a complete update to our Azure Integration packages like this (as well as DataProtection) coming soon (as part of the 3.1 series of packages). The newer Azure SDK packages include breaking changes so these will be introduced as new packages rather than an update to the existing ones. However, the API is the same (the "breaking change" is that they bring in the new Azure SDK, which may be breaking to your app if you are using the SDK directly somewhere).

FYI: The 2.2 packages are end-of-life and 3.0 is not far behind it. I'd suggest moving to 3.1 when these new packages are released (I'll update this thread when that happens). See the full .NET Core support policy for more information.

I am seeing the same issue with 3.1.1 on netCore3.1. I am trying to build with following references.

<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="3.1.1" />
<PackageReference Include="Microsoft.ServiceFabric.AspNetCore.Kestrel" Version="4.0.464" />
<PackageReference Include="Microsoft.Bot.Builder.Integration.AspNet.Core" Version="4.7.2" />
<PackageReference Include="Microsoft.Extensions.Configuration.AzureKeyVault" Version="3.1.1" />

I'm having the same problem when running a .NET Core 3.1 app and referencing Microsoft.Extensions.Configuration.AzureKeyVault version 3.1.1. Shame that this issue has been lying around for so long without a resolution. Would be good to be able to reference our Key Vault from our own infrastructure as easily as we can with an Azure hosted app. @anurse do you have any time estimates on when the newer Azure SDK packages will be available? Or where I can look out for them?

https://www.nuget.org/packages/Microsoft.Azure.Services.AppAuthentication/1.4.0 has been released

Can we get an update on when Microsoft.Extensions.Configuration.AzureKeyVault will be modified to use it?

Same issue as @dotnetcanuck and @Mdub28. Using a certificate to authorize with key vault.
Found that using client secret works, but that's not really a solution, at best a temporary fix if the cert issue is getting fixed.

Anyways, implementing the keyvault client your self seems to work fine..

public class ShitfixKeyVaultClient : KeyVaultClient
{
    private static readonly TokenCache tokenCache = new TokenCache();
    private static Dictionary<string,X509Certificate2> certificates = new Dictionary<string, X509Certificate2>();

    public ShitfixKeyVaultClient(string clientId, string thumbprint) 
        : base((authority, resource, scope) => GetAccessTokenAsync(clientId, thumbprint, authority, resource, scope))
    {
    }

    public static async Task<string> GetAccessTokenAsync(string clientId, string thumbprint, string authority, string resource, string scope)
    {
        var pfx = FindCertificateByThumbprint(thumbprint, StoreLocation.CurrentUser);

        AuthenticationContext authContext = new AuthenticationContext(authority, tokenCache);
        var credentials = new ClientAssertionCertificate(clientId, pfx);
        var authToken = await authContext.AcquireTokenAsync(resource, credentials);
        return authToken.AccessToken;
    }

    private static X509Certificate2 FindCertificateByThumbprint(string findValue, StoreLocation location)
    {
        if (certificates.ContainsKey(findValue))
            return certificates[findValue];

        X509Store store = new X509Store(StoreName.My, location);
        try
        {
            store.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection col = store.Certificates.Find(X509FindType.FindByThumbprint, findValue, false);
            if (col == null || col.Count == 0)
                return null;

            certificates[findValue] = col[0];
            return col[0];
        }
        finally
        {
            store.Close();
        }
    }
}

And can be used like

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .ConfigureAppConfiguration((ctx, configBuilder) =>
        {
            var config = configBuilder.Build();
            var client = new ShitfixKeyVaultClient(config["AzureAd:ClientId"], config["AzureAd:CertThumprint"]);
            configBuilder.AddAzureKeyVault("https://myvault.vault.azure.net", client, new DefaultKeyVaultSecretManager());
        })
        .ConfigureWebHostDefaults(webBuilder =>
        {
            webBuilder.UseStartup<Startup>();
        });

Probably gonne be a better way to do this, but after a day of 馃 馃槙 馃槚 馃槶 馃槧 馃 i'm not gonne spend more time on this 馃槢

Just ran into this as well. The problem is sinister because .Platform it isn't listed as a direct dependency of anything other than AppAuth. However, forcing AppAuth to 1.4 doesn't help as something in the configuration extensions IS referencing platform without stating it's dependency as direct.

Even if this wasn't breaking, this should be fixed to help customers align various dependency chains where possible.

I am having the same issue while trying to use a certificate to authorize with Kv while for secret it works. Our Org doesn't recommend using secrets so a fix for this would be great from Kv PG team

Using .net core 3.1
Microsoft.Extensions.Configuration.AzureKeyVault v3.1.3

Please try the new packages now available from the Azure SDK team. See https://github.com/aspnet/Announcements/issues/408 for details.

A preview version is now available, and they support .NET Core 2.1 and 3.1.

Closing as we believe the new Azure SDK packages resolve this problem. Let us know by filing new issues if you are still encountering problems with the existing Microsoft.Extensions... packages and cannot migrate.

Was this page helpful?
0 / 5 - 0 ratings