ADAL V3、Azure Data Lake、证书和 ServiceClientCredentials

ADAL V3, Azure Data Lake, Certificates and ServiceClientCredentials

我有点麻烦,我需要在同一段代码 (C#) 中从同一服务主体访问 Azure 事件中心和 Azure 数据湖。服务主体是一个 Azure AD 应用程序,我正在使用证书进行身份验证。

如果我使用 ADAL 2.x 并进行身份验证,我可以正常连接到 Azure Data Lake,但事件中心 (WindowsAzure.ServiceBus) 无法进行身份验证(请参阅下文)。

我用来为 Azure Data Lake 创建凭据的 ADAL 2.x 代码如下,100% 正常:

  public static ServiceClientCredentials GetCreds_SPI_Cert(string tenant, Uri tokenAudience, string clientId, string certificateThumbprint)
        {
            var certificate = FindCertificateByThumbprint(certificateThumbprint);

            SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());

            var clientAssertionCertificate = new ClientAssertionCertificate(clientId, certificate);
            var serviceSettings = ActiveDirectoryServiceSettings.Azure;
            serviceSettings.TokenAudience = tokenAudience;

            var creds = ApplicationTokenProvider.LoginSilentWithCertificateAsync(tenant, clientAssertionCertificate, serviceSettings).GetAwaiter().GetResult();
            return creds;
        }

如果我升级到 ADAL v3 以获得事件中心的访问权限(WindowsAzure.ServiceBus 需要它),则以下代码可以正常工作(对于事件中心):

public static TokenProvider GetTokenProviderViaCetificate(string tenant, Uri tokenAudience, string clientId, string certificateThumbprint)
{
    var certificate = FindCertificateByThumbprint(certificateThumbprint);
    return TokenProvider.CreateAadTokenProvider(
        new AuthenticationContext($"https://login.windows.net/{tenant}"),
        new ClientAssertionCertificate(clientId, certificate),
        ServiceAudience.EventHubsAudience);
}

请注意,事件中心身份验证中的令牌提供程序 CreateAadTokenProvider 仅在 ADALv3 中可用。服务总线和数据湖客户端也都需要不同类型的凭证。

如果我使用 ADAL V3 并返回到数据湖代码,GetCreds_SPI_Cert 会失败并出现以下错误:

Method not found: 'System.Threading.Tasks.Task`1 Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext.AcquireTokenAsync(System.String, Microsoft.IdentityModel.Clients.ActiveDirectory.ClientAssertionCertificate)'.

简而言之,我如何使用 ADAL v3 针对 Azure Data Lake 验证 Azure AD 应用服务主体(使用证书)?由于事件中心依赖性,我无法降级到 ADAL 2.x。

可以帮助设计一个解决方案的东西,尽管可能不是直接的解决方案,是在 github 存储库深处记录的身份验证适配器:

https://github.com/Azure/azure-sdk-for-net/blob/3f736b5af3851ab99bbaa98483ae537de0d48cfb/Documentation/AuthConflictsBetweenSDKs.md

Authentication conflicts can happen due to mixing old SDKs* and new SDKs*. SDKs that depend on The credential types created by the new authentication library (Microsoft.Rest.ClientRuntime.Azure.Authentication, type = ServiceClientCredentials) are incompatible with the credential types used in older SDKs (Microsoft.Azure.Common, type = SubscriptionCloudCredentials). The problem is that using two different authentication libraries will require you to authenticate twice, which is a painful experience.

public class SubscriptionCredentialsAdapter : SubscriptionCloudCredentials
{
    ServiceClientCredentials _credentials;
    string _subscriptionId;

    public SubscriptionCredentialsAdapter(ServiceClientCredentials wrapped, string subscriptionId)
    {
        _credentials = wrapped;
        _subscriptionId = subscriptionId;
    }

    public override string SubscriptionId
    {
        get { return _subscriptionId; }
    }

    public override Task ProcessHttpRequestAsync(HttpRequestMessage request, CancellationToken cancellationToken)
    {
       return _credentials.ProcessHttpRequestAsync(request, cancellationToken);
    }
}