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 存储库深处记录的身份验证适配器:
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);
}
}
我有点麻烦,我需要在同一段代码 (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 存储库深处记录的身份验证适配器:
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);
}
}