找不到方法:AcquireToken(System.String,Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate)

时间:2018-07-05 21:16:41

标签: c# .net azure azure-active-directory adal

我按照以下文档使用Azure AD应用程序注册创建了x509证书。

https://docs.microsoft.com/en-us/sharepoint/dev/solution-guidance/security-apponly-azuread

我生成了.pfx文件,设置了密码,并且还在租户Azure AD中注册了该应用程序,然后使用keycredentials部分更新了清单。

然后,我正在创建一个WEB API,该API可以接收一些参数,包括.pfx文件。

 [HttpPut]
        public async Task<IHttpActionResult> PutTenant([ModelBinder(typeof(TenantModelBinder))] Tenant tenant)
        {
            try
            {               
                var cert = new X509Certificate2(tenant.CertificateFile, tenant.CertificatePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable);

                using (var cc = new OfficeDevPnP.Core.AuthenticationManager().GetAzureADAppOnlyAuthenticatedContext(tenant.SiteCollectionTestUrl, tenant.ApplicationId, tenant.TenantDomainUrl, cert))
                {
                    cc.Load(cc.Web, p => p.Title);
                    cc.ExecuteQuery();
                };
            }
            catch (System.Exception)
            {
                return BadRequest("Configuration Invalid");
            }

我正在使用来自HttpRequest的字节数组来创建x509对象。

但是我收到此错误:

Message "Method not found: 'Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationResult Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.AcquireToken(System.String, Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate)'."   string

Stacktrace:

at OfficeDevPnP.Core.AuthenticationManager.<>c__DisplayClass36_0.<GetAzureADAppOnlyAuthenticatedContext>b__0(Object sender, WebRequestEventArgs args)\r\n   at Microsoft.SharePoint.Client.ClientRuntimeContext.OnExecutingWebRequest(WebRequestEventArgs args)\r\n   at Microsoft.SharePoint.Client.ClientContext.GetWebRequestExecutor()\r\n   at Microsoft.SharePoint.Client.ClientContext.GetFormDigestInfoPrivate()\r\n   at Microsoft.SharePoint.Client.ClientContext.EnsureFormDigest()\r\n   at Microsoft.SharePoint.Client.ClientContext.ExecuteQuery()\r\n   at TenantManagementWebApi.Controllers.TenantController.<PutTenant>d__2.MoveNext() in C:\\Users\\levm3\\source\\repos\\TenantManagementWebApi\\Controllers\\TenantController.cs

在执行查询中引发错误

这里真的很无知。

更新:

我在我的web.config中注意到了这一点

 <dependentAssembly>
        <assemblyIdentity name="Microsoft.IdentityModel.Clients.ActiveDirectory" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-3.19.5.13701" newVersion="3.19.5.13701"/>
      </dependentAssembly>

这在我的packages.config上

  <package id="Microsoft.IdentityModel.Clients.ActiveDirectory" version="3.19.5" targetFramework="net461" />

1 个答案:

答案 0 :(得分:3)

PnP Core当前使用2.29.0软件包的旧版本Microsoft.IdentityModel.Clients.ActiveDirectory

最好是将API项目中使用的版本降级为PnP Framework使用的版本,这肯定会起作用。

与该错误有关,框架在内部调用AuthenticationContext.AcquireToken方法,该方法已在较新的Nuget v3软件包中弃用。

因此,似乎PnP代码正在调用此方法属于v2版本,而要使用的v3软件包的正确方法是v3版本的AcquireTokenAsync,这会导致冲突。

参考-OfficeDevPnP Core package.config文件

现在,我们可以看到已经有PR到位来更新PnP Framework本身中的nuget包,一旦被接受,它将立即解决您的问题。但是可能需要一些时间才能被接受,所以不要屏住呼吸:)

AuthenticationResult.AcquireToken deprecated in ADAL 3.x and how to fix.

Microsoft文档-AuthenticationContext.AcquireTokenAsync Method

最好是将API项目降级到v2或等待PnP框架升级程序包及其必需的依赖项。

另一个选项,如果您仅使用PnP进行身份验证,则可以使用以下帮助程序方法,该方法不需要您更改软件包。但是,如果您使用其他功能(例如配置或其他扩展),那么很遗憾需要降级。这是对PnP本身内部使用的内容进行了修改,以利用v3软件包的更改:

public ClientContext GetAzureADAppOnlyAuthenticatedContext(string siteUrl, string clientId, string tenant, X509Certificate2 certificate)
{
    var clientContext = new ClientContext(siteUrl);

    string authority = string.Format(CultureInfo.InvariantCulture, "https://login.windows.net/{0}/", tenant);

    var authContext = new AuthenticationContext(authority);

    var clientAssertionCertificate = new ClientAssertionCertificate(clientId, certificate);

    var host = new Uri(siteUrl);

    clientContext.ExecutingWebRequest += (sender, args) =>
    {
        var ar = authContext.AcquireTokenAsync(host.Scheme + "://" + host.Host + "/", clientAssertionCertificate).GetAwaiter().GetResult();
        args.WebRequestExecutor.RequestHeaders["Authorization"] = "Bearer " + ar.AccessToken;
    };

    return clientContext;
}