更新 Microsoft Graph 后未找到 DelegateAuthenticationProvider

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?

Tin*_*ang 9

我还没有弄清楚你的问题,因为我以前从未使用过你的代码,我只是按照这个官方文档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 范围生成时,我将成功验证图形客户端。

在此输入图像描述


use*_*152 8

对于 Microsoft.Graph v5.0.0,GraphServiceClient构造函数接受TokenCredentialfromAzure.Identity包的实例。

有很多从TokenCredential派生的类,例如 InteractiveBrowserCredentialClientSecretCredential

示例InteractiveBrowserCredential

var interactiveBrowserCredential = new InteractiveBrowserCredential(interactiveBrowserCredentialOptions);
var graphServiceClient = new GraphServiceClient(interactiveBrowserCredential);
Run Code Online (Sandbox Code Playgroud)

不确定,但可能OnBehalfOfCredential类类似于 Microsoft.IdentityUserAssertion

资源:

升级到v5:身份验证


Mor*_*lay 5

也有同样的问题,我根据文档解决了它: 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)

希望能帮助到你。