Vej
Vej

Reputation: 400

Missing Assembly Reference Using Microsoft.IdentityModel.Clients.ActiveDirectory 3.13.9 with Azure KeyVault C# SDK

For some reason, I have to latest Microsoft.IdentityModel.Clients.ActiveDirectory v3.13.9 with Microsoft.Azure.KeyVault v2.0.6. And it always throws exceptions for missing assembly reference, but downgrading Microsoft.IdentityModel.Clients.ActiveDirectory to v2.28.4, which I'm not allowed to use, can resolve this known issue.

Here's the exception:

  InnerException:
   HResult=-2146233036
   Message=The type initializer for 'Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformPlugin' threw an exception.
   Source=Microsoft.IdentityModel.Clients.ActiveDirectory
   TypeName=Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformPlugin
   StackTrace:
        at Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformPlugin.get_Logger()
        at Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext..cctor()
   InnerException:
        ErrorCode=assembly_not_found
        HResult=-2146233088
        Message=Assembly required for the platform not found. Make sure assembly 'Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.12.0.827, Culture=neutral, PublicKeyToken=31bf3856ad364e35' exists
        Source=Microsoft.IdentityModel.Clients.ActiveDirectory
        StackTrace:
             at Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformPlugin.LoadPlatformSpecificAssembly()
             at Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformPlugin.InitializeByAssemblyDynamicLinking()
             at Microsoft.IdentityModel.Clients.ActiveDirectory.PlatformPlugin..cctor()
        InnerException:
             FileName=Microsoft.IdentityModel.Clients.ActiveDirectory.Platform, Version=3.12.0.827, Culture=neutral, PublicKeyToken=31bf3856ad364e35
             FusionLog==== Pre-bind state information ===

Code snippets:

    protected KeyVaultBase(string clientId, string clientSecret)
    {
        if (string.IsNullOrWhiteSpace(clientId))
        {
            throw new ArgumentNullException(nameof(clientId));
        }

        if (string.IsNullOrWhiteSpace(clientSecret))
        {
            throw new ArgumentNullException(nameof(clientSecret));
        }

        this.KeyVaultClient = new KeyVaultClient(
            new KeyVaultClient.AuthenticationCallback(
                (authority, resource, scope) => GetAccessToken(authority, resource, scope, clientId, clientSecret)
            )
        );
    }

    private static async Task<string> GetAccessToken(string authority, string resource, string scope, string clientId, string clientSecret)
    {
        var authnContext = new AuthenticationContext(authority);
        var clientCredential = new ClientCredential(clientId, clientSecret);
        var result = await authnContext.AcquireTokenAsync(resource, clientCredential);

        if (result == null)
        {
            throw new InvalidOperationException("Failed to obtain the JWT token");
        }

        return result.AccessToken;
    }

The exception throws while executing var authnContext = new AuthenticationContext(authority);.

Does anyone know any solution/workaround to resolve this issue without the downgrading?

Upvotes: 2

Views: 4270

Answers (2)

Andr&#233; Pires
Andr&#233; Pires

Reputation: 51

In my case the references were installed only to the class library project, not to the executing assembly, so it was throwing this exception.

Adding the Microsoft.IdentityModel.Clients.ActiveDirectory nuget package to the executing assembly worked for me.

Hope it helps

Upvotes: 3

Tom Sun
Tom Sun

Reputation: 24569

Please have a try uninstall both of Microsoft.IdentityModel.Clients.ActiveDirectory v3.13.9 and Microsoft.Azure.KeyVault v2.0.6 then reinstall them again. If there are multiple projects in the solution are referenced them, please make sure all of the them are the same version.

I create a console or Asp.net MVC project, both are working correctly on my side using Microsoft.IdentityModel.Clients.ActiveDirectory v3.13.9 with Microsoft.Azure.KeyVault v2.0.6.

The following is my detail steps:

1.Create a C# console project.

2.Add the Microsoft.IdentityModel.Clients.ActiveDirectory v3.13.9 with nuget.

3.Add the Microsoft.Azure.KeyVault v2.0.6 from Package manager console with command

Install-Package Microsoft.Azure.KeyVault -Version 2.0.6

Packages.config file:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Microsoft.Azure.KeyVault" version="2.0.6" targetFramework="net452" />
  <package id="Microsoft.Azure.KeyVault.WebKey" version="2.0.4" targetFramework="net452" />
  <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.13.9" targetFramework="net452" />
  <package id="Microsoft.Rest.ClientRuntime" version="2.3.2" targetFramework="net452" />
  <package id="Microsoft.Rest.ClientRuntime.Azure" version="3.3.1" targetFramework="net452" />
  <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net452" />
</packages>

Add a class in the project:

 class KeyVaultBase
    {

        static string _clientId= "xxxxxxxxxxxxx";
        static string _clientSecret = "xxxxxxxxxxxxxxxx";
        static string _tenantId = "xxxxxxxxxxxxxxxx";
        public static async Task<string> GetAccessToken(string azureTenantId, string azureAppId, string azureSecretKey)
        {

            var context = new AuthenticationContext("https://login.windows.net/" + _tenantId);
            ClientCredential clientCredential = new ClientCredential(_clientId, _clientSecret);
            var tokenResponse = await context.AcquireTokenAsync("https://vault.azure.net", clientCredential);
            var accessToken = tokenResponse.AccessToken;
            return accessToken;
        }

    }

4.Test Get Secret from the KeyVault

static void Main(string[] args)
        {
            var kv = new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(KeyVaultBase.GetAccessToken));
            string secretUri = "https://KeyVaultNameSpace.vault.azure.net/secrets/secretsname/6341322679db4f3491814ff6178dee45";
            var sec = kv.GetSecretAsync(secretUri).Result;
        }

enter image description here

Upvotes: 0

Related Questions