Shi*_*iji 16 c# oauth-2.0 azure-ad-msal asp.net-core-webapi microsoft-graph-api
我有以下代码(从 Microsoft Learn 复制),在 Microsoft.Graph 4.54.0 上运行良好
var authProvider = new DelegateAuthenticationProvider(async (request) => {
// Use Microsoft.Identity.Client to retrieve token
var assertion = new UserAssertion(token.AccessToken);
var result = await clientApplication.AcquireTokenOnBehalfOf(scopes, assertion).ExecuteAsync();
request.Headers.Authorization =
new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", result.AccessToken);
});
Run Code Online (Sandbox Code Playgroud)
然后,我使用 Microsoft.Graph 5.0.0 和 Microsoft.Graph.Core 3.0.0 创建了一个新项目,这给出了无法找到 DelegateAuthenticationProvider 的错误。
如何创建可与 GraphServiceClient 一起使用的 AuthenticationProvider?
我还没有弄清楚你的问题,因为我以前从未使用过你的代码,我只是按照这个官方文档GraphServiceClient通过代流程创建。我会尝试继续。这是我已经得到的并且有效的。
using Azure.Core;
using Azure.Identity;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Microsoft.Graph;
namespace WebMvcGraph5Ofo.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class HelloController : ControllerBase
{
public async Task<string> Get() {
StringValues authorizationToken;
HttpContext.Request.Headers.TryGetValue("Authorization", out authorizationToken);
var token = authorizationToken.ToString().Replace("Bearer ","");
var scopes = new[] { "User.Read.All" };
var tenantId = "tenantId";
var clientId = "client_id";
var clientSecret = "client_secret";
var onBehalfOfCredential = new OnBehalfOfCredential(tenantId, clientId, clientSecret, token);
var tokenRequestContext = new TokenRequestContext(scopes);
var token2 = onBehalfOfCredential.GetTokenAsync(tokenRequestContext, new CancellationToken()).Result.Token;
var graphClient = new GraphServiceClient(onBehalfOfCredential, scopes);
var user = await graphClient.Users.GetAsync();
return "hello";
}
[Route("ClientCredentialFlow")]
public async Task<string> clientAsync() {
var scopes = new[] { "https://graph.microsoft.com/.default" };
var tenantId = "tenantId";
var clientId = "client_id";
var clientSecret = "client_secret";
var clientSecretCredential = new ClientSecretCredential(
tenantId, clientId, clientSecret);
var graphClient = new GraphServiceClient(clientSecretCredential, scopes);
var users = await graphClient.Users.GetAsync();
return "world";
}
[Route("provider")]
public async Task<string> providerAsync()
{
StringValues authorizationToken;
HttpContext.Request.Headers.TryGetValue("Authorization", out authorizationToken);
string incomingToken = authorizationToken.ToString().Replace("Bearer ", "");
TokenProvider provider = new TokenProvider();
provider.token = incomingToken;
var authenticationProvider = new BaseBearerTokenAuthenticationProvider(provider);
var graphServiceClient = new GraphServiceClient(authenticationProvider);
var user = await graphServiceClient.Users.GetAsync();
return "!!";
}
}
public class TokenProvider : IAccessTokenProvider
{
public string token { get; set; }
public AllowedHostsValidator AllowedHostsValidator => throw new NotImplementedException();
public Task<string> GetAuthorizationTokenAsync(Uri uri, Dictionary<string, object>? additionalAuthenticationContext = null, CancellationToken cancellationToken = default)
{
return Task.FromResult(token);
}
}
}
Run Code Online (Sandbox Code Playgroud)
=================================================== =======
就像@user2250152分享的那样,
可以使用自定义身份验证流程来代替 DelegateAuthenticationProvider,创建 IAccessTokenProvider 的实现,并与 Kiota 抽象中的 BaseBearerTokenAuthenticationProvider 一起使用,如下所示
我们不能DelegateAuthenticationProvider再直接使用to了new GraphServiceClient(delegateAuthenticationProvider),如果我们要生成auth_provider to new GraphServiceClient,就得跟着使用BaseBearerTokenAuthenticationProvider + IAccessTokenProvider。我做了如下测试,可以工作,但似乎不符合代流要求。
正如您所知,OBO 的整个流程应该是,使用访问令牌 A 调用受 AAD 保护的 Web API,然后 API 代码使用 OBO 流程生成新的访问令牌 B 来执行其他请求,例如调用图 API。
那么令牌 A 的范围或角色应该类似于api://xxxx/scope_name(.default for role),令牌 B 的范围应该是图形 API 范围,例如User.Read.All。
在我的测试中,我使用了图形客户端,这样我就不需要生成令牌B,但它仍然需要对图形客户端进行身份验证。我发现当我传递令牌 Aapi://xxxx/scope_name来验证图形客户端时,我会收到错误,但是当令牌 A 由图形 API 范围生成时,我将成功验证图形客户端。
对于 Microsoft.Graph v5.0.0,GraphServiceClient构造函数接受TokenCredentialfromAzure.Identity包的实例。
有很多从TokenCredential派生的类,例如
InteractiveBrowserCredential或ClientSecretCredential
示例InteractiveBrowserCredential
var interactiveBrowserCredential = new InteractiveBrowserCredential(interactiveBrowserCredentialOptions);
var graphServiceClient = new GraphServiceClient(interactiveBrowserCredential);
Run Code Online (Sandbox Code Playgroud)
不确定,但可能OnBehalfOfCredential类类似于 Microsoft.IdentityUserAssertion
资源:
也有同样的问题,我根据文档解决了它: https ://github.com/microsoftgraph/msgraph-sdk-dotnet/blob/feature/5.0/docs/upgrade-to-v5.md#authentication
这是我的解决方案:
public class TokenProvider : IAccessTokenProvider
{
public async Task<string> GetAuthorizationTokenAsync(Uri uri, Dictionary<string, object> additionalAuthenticationContext = default,
CancellationToken cancellationToken = default)
{
//Tried to adjust this part to your code.
// Use Microsoft.Identity.Client to retrieve token
var assertion = new UserAssertion(token.AccessToken);
var result = await clientApplication.AcquireTokenOnBehalfOf(scopes, assertion).ExecuteAsync();
return result.AccessToken;
}
public AllowedHostsValidator AllowedHostsValidator { get; }
}
Run Code Online (Sandbox Code Playgroud)
以及用途:
var authenticationProvider = new BaseBearerTokenAuthenticationProvider(new TokenProvider(configuration));
graphServiceClient = new GraphServiceClient(authenticationProvider);
Run Code Online (Sandbox Code Playgroud)
希望能帮助到你。
| 归档时间: |
|
| 查看次数: |
23414 次 |
| 最近记录: |