gpt4 book ai didi

c# - 使用托管标识从 Azure 应用服务调用图

转载 作者:行者123 更新时间:2023-12-02 06:55:48 32 4
gpt4 key购买 nike

我有一个 .NET 6 Web API 项目,它将 Graph 作为应用程序(而不是代表用户)调用。

我正在使用 Microsoft.Identity.Web 包,我的 Program.cs 有以下代码来初始化它:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddMicrosoftGraphAppOnly(auth => new Microsoft.Graph.GraphServiceClient(auth))
.AddInMemoryTokenCaches();

我已向 Azure AD 应用注册授予必要的图形应用权限(本例中为 User.Read.All)并授予管理员同意。

当我在本地调试时,我在用户 secret 中设置了 ClientSecret,并且以下调用有效:

var photo = await _graph.Users[id].Photo.Content.Request().GetAsync();

但是,当我部署到 Azure 应用服务时,我不想使用 ClientSecret。我想使用我的应用服务的系统分配托管标识。

Microsoft.Identity.Web 显然支持 UserAssignedManagedIdentityClientId 选项,因此我已将环境变量设置为我的应用服务的 ClientID:

UserAssignedManagedIdentityClientID environment variable

...代码似乎确实注意到了这一点。

但是,当我尝试执行图形调用时,出现错误。堆栈跟踪如下所示(敏感信息已编辑):

An unhandled exception has occurred while executing the request.

Exception:
Status Code: 0
Microsoft.Graph.ServiceException: Code: generalException
Message: An error occurred sending the request.

---> MSAL.NetCore.4.42.0.0.MsalServiceException:
ErrorCode: invalid_request
Microsoft.Identity.Client.MsalServiceException: AADSTS70021: No matching federated identity record found for presented assertion. Assertion Issuer: 'https://login.microsoftonline.com/{tenant}/v2.0'. Assertion Subject: '{msi-objectid}'. Assertion Audience: 'fb60f99c-7a34-4190-8149-302f77469936'. https://learn.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation
Trace ID: 7862bb35-0bdd-40c9-9c7b-cb12a8a0f200
Correlation ID: 97f749c8-f91d-434e-9ecd-111c65037399
Timestamp: 2022-03-23 05:11:08Z
at Microsoft.Identity.Client.Internal.Requests.RequestBase.HandleTokenRefreshErrorAsync(MsalServiceException e, MsalAccessTokenCacheItem cachedAccessTokenItem)
at Microsoft.Identity.Client.Internal.Requests.ClientCredentialRequest.ExecuteAsync(CancellationToken cancellationToken)
at Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(CancellationToken cancellationToken)
at Microsoft.Identity.Client.ApiConfig.Executors.ConfidentialClientExecutor.ExecuteAsync(AcquireTokenCommonParameters commonParameters, AcquireTokenForClientParameters clientParameters, CancellationToken cancellationToken)
at Microsoft.Identity.Web.TokenAcquisitionAuthenticationProvider.AuthenticateRequestAsync(HttpRequestMessage request)
at Microsoft.Graph.AuthenticationHandler.SendAsync(HttpRequestMessage httpRequestMessage, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.<SendAsync>g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
at Microsoft.Graph.HttpProvider.SendRequestAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
StatusCode: 400
ResponseBody: {"error":"invalid_request","error_description":"AADSTS70021: No matching federated identity record found for presented assertion. Assertion Issuer: 'https://login.microsoftonline.com/{tenant}/v2.0'. Assertion Subject: '{msi-objectid}'. Assertion Audience: 'fb60f99c-7a34-4190-8149-302f77469936'. https://learn.microsoft.com/en-us/azure/active-directory/develop/workload-identity-federation\r\nTrace ID: 7862bb35-0bdd-40c9-9c7b-cb12a8a0f200\r\nCorrelation ID: 97f749c8-f91d-434e-9ecd-111c65037399\r\nTimestamp: 2022-03-23 05:11:08Z","error_codes":[70021],"timestamp":"2022-03-23 05:11:08Z","trace_id":"7862bb35-0bdd-40c9-9c7b-cb12a8a0f200","correlation_id":"97f749c8-f91d-434e-9ecd-111c65037399","error_uri":"https://login.microsoftonline.com/error?code=70021"}
Headers: Cache-Control: no-store, no-cache

这里有趣的是,堆栈跟踪错误中的“断言主题”是我的托管身份的ObjectID,而不是ClientID。所以看起来它已经正确找到了应用服务,但碰壁了。

有人能做到这一点吗?我可以使用我的应用服务的系统管理标识来调用 Graph 吗?

最佳答案

好的,我这里有可以运行的代码。发帖以防对其他人有帮助或万一有人可以批评它并使其变得更好。

本质上,我已经不再使用 .AddMicrosoftGraphAppOnly() 来添加 GraphServiceClient,而是启动一个 ChainedTokenCredential 来检查设置中的 ClientSecret,但也会尝试使用托管身份(如果存在)。

我使用该凭证对象来获取访问 token ,并在其生命周期内对其进行缓存。

当从 Visual Studio 运行且用户 key 中包含 ClientSecret 时,以及在未设置 ClientSecret 的 Azure 应用服务中运行时,此功能有效。

希望这对某人有帮助!如果您认为代码可以改进,请告诉我!

builder.Services.AddSingleton<TokenCredential>(services =>
{
var options = new MicrosoftIdentityOptions();
builder.Configuration.Bind("AzureAd", options);

var creds = new List<TokenCredential> { new ManagedIdentityCredential() };
if (!string.IsNullOrEmpty(options.ClientSecret))
{
creds.Add(new ClientSecretCredential(options.TenantId, options.ClientId, options.ClientSecret));
}
return new ChainedTokenCredential(creds.ToArray());
});

// Add services to the container.
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
.AddInMemoryTokenCaches();

builder.Services.AddScoped(services => new GraphServiceClient(services.GetRequiredService<TokenCredential>()));

(编辑 - 我已经摆脱了 token 缓存代码。我认为 TokenCredential 对象可以为我做到这一点。)

关于c# - 使用托管标识从 Azure 应用服务调用图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71594455/

32 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com