Visual Studio 2019 TokenService.exe失败,出现意外错误:TS003:错误,TS004:



环境:

Microsoft Visual Studio Community 2019
Version 16.11.9
VisualStudio.16.Release/16.11.9+32106.194

目标框架是.NET 5.0

使用Visual Studio建立与Azure密钥保管库的连接时,正在尝试本地测试。使用新的Azure Identity客户端库。

NuGet软件包已安装:

  • Azure.Identity
  • Azure.Extensions.AspNetCore.Configuration.Secrets

相关代码如下所示:

using Azure.Identity;
Microsoft.Extensions.Configuration.ConfigurationBuilder config_builder;
Azure.Identity.DefaultAzureCredentialOptions default_azure_credential_options;
Azure.Identity.DefaultAzureCredential azure_credential_default;

// Exclude all to begin with ...
default_azure_credential_options = new DefaultAzureCredentialOptions
{
ExcludeAzureCliCredential = true,
ExcludeAzurePowerShellCredential = true,
ExcludeEnvironmentCredential = true,
ExcludeInteractiveBrowserCredential = true,
ExcludeManagedIdentityCredential = true,
ExcludeSharedTokenCacheCredential = true,
ExcludeVisualStudioCodeCredential = true,
ExcludeVisualStudioCredential = true
};

// Try to use the Visual Studio credential ...
default_azure_credential_options.ExcludeVisualStudioCredential = false;
// Create credentials and add Azure KeyVault config keys / values ...
azure_credential_default = new DefaultAzureCredential( default_azure_credential_options );
config_builder.AddAzureKeyVault( keyvault_uri, azure_credential_default );
...
config_builder.Build();

根据文档,我已通过Visual Studio登录到我们的Azure帐户。

此外,根据文档,当出现此错误时,我会注销并再次登录到我们的Azure帐户(再次通过Visual Studio(。但是,当调用Build((方法时,会引发以下异常:

Azure.Identity.CredentialUnavailableException: Process "D:appsVStudioNet2019Common7IDEExtensionsrahssdlq.j5oTokenServiceMicrosoft.Asal.TokenService.exe" has failed with unexpected error: TS003: Error, TS004: Unable to get access token.  'AADSTS50020: User account '{EmailHidden}' from identity provider 'live.com' does not exist in tenant 'Microsoft Services' and cannot access the application '872cd9fa-d31f-45e0-9eab-6e460a02d1f1'(Visual Studio) in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.
Trace ID: 819fe58d-fe72-4688-9750-d88409882f00
Correlation ID: 7443c9c8-757a-44af-992d-b2576add5941
Timestamp: 2022-01-26 19:24:16Z'.
---> System.InvalidOperationException: TS003: Error, TS004: Unable to get access token.  'AADSTS50020: User account '{EmailHidden}' from identity provider 'live.com' does not exist in tenant 'Microsoft Services' and cannot access the application '872cd9fa-d31f-45e0-9eab-6e460a02d1f1'(Visual Studio) in that tenant. The account needs to be added as an external user in the tenant first. Sign out and sign in again with a different Azure Active Directory user account.
Trace ID: 819fe58d-fe72-4688-9750-d88409882f00
Correlation ID: 7443c9c8-757a-44af-992d-b2576add5941
Timestamp: 2022-01-26 19:24:16Z'
at Azure.Identity.VisualStudioCredential.RunProcessesAsync(List`1 processStartInfos, Boolean async, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at Azure.Identity.DefaultAzureCredential.GetTokenFromSourcesAsync(TokenCredential[] sources, TokenRequestContext requestContext, Boolean async, CancellationToken cancellationToken)
at Azure.Identity.DefaultAzureCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
at Azure.Identity.CredentialDiagnosticScope.FailWrapAndThrow(Exception ex, String additionalMessage)
at Azure.Identity.DefaultAzureCredential.GetTokenImplAsync(Boolean async, TokenRequestContext requestContext, CancellationToken cancellationToken)
at Azure.Identity.DefaultAzureCredential.GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken)
at Azure.Security.KeyVault.ChallengeBasedAuthenticationPolicy.AuthenticateRequestAsync(HttpMessage message, Boolean async)
at Azure.Security.KeyVault.ChallengeBasedAuthenticationPolicy.ProcessCoreAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
at Azure.Core.Pipeline.RedirectPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
at Azure.Core.Pipeline.RetryPolicy.ProcessAsync(HttpMessage message, ReadOnlyMemory`1 pipeline, Boolean async)
at Azure.Core.Pipeline.HttpPipeline.SendRequestAsync(Request request, CancellationToken cancellationToken)
at Azure.Security.KeyVault.KeyVaultPipeline.SendRequestAsync(Request request, CancellationToken cancellationToken)
at Azure.Security.KeyVault.KeyVaultPipeline.GetPageAsync[T](Uri firstPageUri, String nextLink, Func`1 itemFactory, String operationName, CancellationToken cancellationToken)
at Azure.Core.PageResponseEnumerator.FuncAsyncPageable`1.AsPages(String continuationToken, Nullable`1 pageSizeHint)+MoveNext()
at Azure.Core.PageResponseEnumerator.FuncAsyncPageable`1.AsPages(String continuationToken, Nullable`1 pageSizeHint)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()
at Azure.AsyncPageable`1.GetAsyncEnumerator(CancellationToken cancellationToken)+MoveNext()
at Azure.AsyncPageable`1.GetAsyncEnumerator(CancellationToken cancellationToken)+MoveNext()
at Azure.AsyncPageable`1.GetAsyncEnumerator(CancellationToken cancellationToken)+System.Threading.Tasks.Sources.IValueTaskSource<System.Boolean>.GetResult()
at Azure.Extensions.AspNetCore.Configuration.Secrets.AzureKeyVaultConfigurationProvider.LoadAsync()
at Azure.Extensions.AspNetCore.Configuration.Secrets.AzureKeyVaultConfigurationProvider.LoadAsync()
at Azure.Extensions.AspNetCore.Configuration.Secrets.AzureKeyVaultConfigurationProvider.Load()
at Microsoft.Extensions.Configuration.ConfigurationRoot..ctor(IList`1 providers)
at Microsoft.Extensions.Configuration.ConfigurationBuilder.Build()

已经咨询并尝试了以下内容(没有任何帮助或效果(:

  • https://learn.microsoft.com/en-us/dotnet/api/overview/azure/service-to-service-authentication#appauthentication-故障排除

  • https://github.com/Azure/azure-sdk-for-net/blob/main/sdk/identity/Azure.Identity/TROUBLESHOOTING.md#troubleshooting-默认azure凭据身份验证问题

是否有人提供了如何使用VisualStudio凭据进行身份验证的工作示例(逐步(?

附带说明一下,如果我将ExcludeAzureCliCredential设置为false,并通过Azure CLI登录到我们的Azure帐户,一切都会正常工作——但我仍然想知道如何使VisualStudio凭据选项正常工作。

更新:2022年1月27日

终于能够让Visual Studio凭据正常工作了——但是,它需要提供租户ID。修改后的代码是:

Microsoft.Extensions.Configuration.ConfigurationBuilder config_builder;
Azure.Identity.DefaultAzureCredentialOptions default_azure_credential_options;
Azure.Identity.DefaultAzureCredential azure_credential_default;

// Exclude all to begin with ...
default_azure_credential_options = new DefaultAzureCredentialOptions
{
ExcludeAzureCliCredential = true,
ExcludeAzurePowerShellCredential = true,
ExcludeEnvironmentCredential = true,
ExcludeInteractiveBrowserCredential = true,
ExcludeManagedIdentityCredential = true,
ExcludeSharedTokenCacheCredential = true,
ExcludeVisualStudioCodeCredential = true,
ExcludeVisualStudioCredential = true
};

// Try to use the Visual Studio credential ...
default_azure_credential_options.ExcludeVisualStudioCredential = false;

/*
The tenant ID of the user to authenticate.  The default is null and will authenticate users to 
their default tenant. The value can also be set by setting the environment variable AZURE_TENANT_ID.
Here we set the value explicitly.  The value was obtained AFTER logging into Azure via the CLI, i.e.:
> az login
> az account list
[
{
...
"tenantId": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
...
}
]
*/
default_azure_credential_options.VisualStudioTenantId = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
// Create credentials and add Azure KeyVault config keys / values ...
azure_credential_default = new DefaultAzureCredential( default_azure_credential_options );
config_builder.AddAzureKeyVault( keyvault_uri, azure_credential_default );
...
config_builder.Build();

上面的代码确实有效,但是,我似乎在官方文档中找不到任何声明租户ID是必需的。据我所知,在通过Visual Studio IDE登录Azure后,应该自动获取凭据(但这不起作用(。请参阅Azure Identity客户端库.NET版本1.5.0的官方文档中的通过Visual Studio进行身份验证部分-没有提到需要租户ID。

提前谢谢。

感谢@Christopher Scott-解决方案是安装以下NuGet包:

PM> Install-Package Azure.Security.KeyVault.Secrets -Version 4.3.0-beta.4

上述包装";具有将尝试执行租户发现的新功能";。

一旦上述包包含在项目中,我就可以使用Visual Studio凭据在本地运行应用程序,而无需显式设置租户ID。

希望Azure.Extensions.AspNetCore.Configuration.Secrets包能很快更新,以使用更新的Azure.Security.KeyVault.Secrets包(它依赖于此(,然后只需要使用原始的两个NuGet包(根据原始帖子(。

我在VS 2019和VS 2022中都有相同的错误,但原因不同。我的应用程序使用凭据与Azure Storage对话,而且它正在获取我的作用域的令牌。

以上步骤都没有帮助(既没有显式设置Tenant Id,也没有添加Azure.Security.KeyVault.Secrets包(。

private async Task RetrieveAccessToken()
{
TokenRequestContext tokenRequestContext = new TokenRequestContext(new[] { scope });
this.AccessToken = await this.tokenCredential.GetTokenAsync(tokenRequestContext, CancellationToken.None);
}

最初,我创建了DefaultAzureCredential的一个实例,导致了这个错误。最后,帮助的是提取其创建的逻辑,并在需要的地方传递独立的实例:

private static TokenCredential CreateCredential(string managedIdentityClientId)
{
TokenCredential tokenCredential;
if (string.Equals(managedIdentityClientId, "dev", StringComparison.OrdinalIgnoreCase))
{
tokenCredential = new DefaultAzureCredential();
}
else
{
tokenCredential = new ManagedIdentityCredential(managedIdentityClientId);
}
return tokenCredential;
}

我不知道它为什么会这样。注意,Azure存储仍然可以重用(我有两层需要它(。但为我的自定义作用域请求令牌需要新的实例。

ManagedIdentityCredential的情况并非如此——它可以很好地处理重用的单个实例。

最新更新