如何使用客户端应用程序中的访问令牌从 Blazor WASM 托管解决方案中的服务器应用程序调用 MS Graph API?

问题描述 投票:0回答:1

客户端 FE 应用程序 (Blazor WASM) 登录用户,然后将访问令牌传递到服务器 BE 应用程序 (ASP.NET Core Web API)。现在,我想以某种方式将 Graph 客户端添加到服务器应用程序中的 DI 容器,并从那里的服务和控制器调用 Graph API。我该怎么做?

客户端应用程序配置

客户端-Program.cs

builder.Services.AddMsalAuthentication(options =>
{
    builder.Configuration.Bind("AzureAd", options.ProviderOptions);
});

builder.Services
    .AddHttpClient(HttpClients.SERVER_API, client =>
    {
        client.BaseAddress = new Uri(appSettings.ServerApi.Url);
    })
    // This configues the client to add the JWT to the 'Authorization' header
    // for every request made to the authorized URLs.
    .AddHttpMessageHandler(sp =>
        sp.GetRequiredService<AuthorizationMessageHandler>()
            .ConfigureHandler(
                authorizedUrls: [ appSettings.ServerApi.Url ],
                scopes: [ appSettings.ServerApi.AccessScope ]
            ));

客户端 - appsettings.json

"AzureAd": {
    "Authentication": {
        "Authority": "https://login.microsoftonline.com/my-authority-here",
        "ClientId": "client-id-here"
    },
    "DefaultAccessTokenScopes": [
        "api://server-app-id-here/API.Access",
        "https://graph.microsoft.com/User.Read"
    ]
}

服务器应用程序配置

服务器 - Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration)
    .EnableTokenAcquisitionToCallDownstreamApi()
    .AddMicrosoftGraph(builder.Configuration.GetSection("DownstreamApis:MicrosoftGraph"))
    .AddInMemoryTokenCaches();

服务器 - appsettings.json

"AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "myusername.onmicrosoft.com",
    "TenantId": "my-tenant-id",
    "ClientId": "server-app-client-id",
    "ClientSecret": "server-app-secret",
    "Scopes": "API.Access",
    "CallbackPath": "/signin-oidc"
},
"DownstreamApis": {
    "MicrosoftGraph": {
        "BaseUrl": "https://graph.microsoft.com/v1.0",
        "Scopes": "User.Read"
    }
},

服务器-调用图

using Microsoft.AspNetCore.Mvc;
using Microsoft.Graph;
using Microsoft.Identity.Web;

namespace ChatPortal.Server.Controllers;

[Route("api/[controller]")]
[ApiController]
public class TestController : ControllerBase
{
    private readonly GraphServiceClient _graphClient;

    public TestController(GraphServiceClient graphClient)
    {
        _graphClient = graphClient;
    }

    [HttpGet("graph")]
    public async Task<IActionResult> GraphTest()
    {
        var user = await _graphClient.Me.GetAsync();

        return Ok();
    }
}

Azure 设置

客户端应用程序注册

API权限:

  • MyServerApp:API.Access,类型:委托,状态:已授予
  • Microsoft Graph:用户.读取,类型:委托,状态:已授予

服务器应用程序注册

公开API:

  • 范围:api://my-server-app-id-here/API.Access
  • 授权的客户端应用程序:my-client-app-id-here

问题

如果我将客户端

"https://graph.microsoft.com/User.Read"
文件中的
DefaultAccessTokenScopes
范围删除为
appsettings.json
,我在尝试调用 Graph 时会收到此错误:

[12:47:58 ERR] An unhandled exception has occurred while executing the request.
Microsoft.Identity.Web.MicrosoftIdentityWebChallengeUserException: IDW10502: An MsalUiRequiredException was thrown due to a challenge for the user. See https://aka.ms/ms-id-web/ca_incremental-consent.
 ---> MSAL.NetCore.4.66.1.0.MsalUiRequiredException:
        ErrorCode: invalid_grant
Microsoft.Identity.Client.MsalUiRequiredException: AADSTS65001: The user or administrator has not consented to use the application with ID 'my-id-here' named 'ChatPortal.Server'. Send an interactive authorization request for this user and resource.

我尝试按照错误提供的“管理增量同意”链接并通过

TestController
获取
ITokenAcquisition
中的令牌,但这似乎试图从 Azure 获取令牌。对于这种情况,这似乎不正确(并且不起作用)——我已经在
Request.Headers.Authorization
属性中拥有访问令牌。问题是我如何将它与 GraphServiceClient 一起使用...

如果我将

User.Read
范围保留在
DefaultAccessTokenScopes
中,这就是我得到的错误:

Request URL: https://login.microsoftonline.com/my-tentant-id-here/oauth2/v2.0/token
Invalid request: AADSTS28000: Provided value for the input parameter scope is not valid because it contains more than one resource. Scope api://server-app-id-here/API.Access https://graph.microsoft.com/User.Read openid profile offline_access is not valid.
c# .net azure-active-directory blazor microsoft-graph-api
1个回答
0
投票

注意:您不能将两个或多个资源作为生成令牌或在请求中传递的范围。

对于 sample,我尝试生成令牌并传递 scope 作为 API 和 Microsoft Graph API:

GET https://login.microsoftonline.com/TenantID/oauth2/v2.0/token

client_id: ClientID
grant_type: authorization_code
scope: api://xxx/ScopeName https://graph.microsoft.com/User.Read openid profile offline_access
redirect_uri: RedirectURL
code: code
client_secret: Secret

enter image description here

并得到相同的错误

enter image description here

错误 “AADSTS28000:为输入参数范围提供的值无效,因为它包含多个资源。范围 api://xxx/claims.read https://graph.microsoft.com/User.Read openid 配置文件离线访问无效。“ 如果您在请求中传递两个或多个不同的资源作为范围,通常会发生这种情况。

  • 一个访问令牌只能包含一个 aud ,在您的情况下,一个令牌无法调用 API 和 Microsoft Graph。
  • 访问令牌中的 aud 声明是为创建令牌的特定 API 或资源指定的。

因此,要解决该错误,您需要发出两个不同的请求,一个调用 API,另一个请求调用 Microsoft Graph API:

调用 API 传递 scope

api://xxx/ScopeName
:

enter image description here

要调用 Microsoft Graph API,请将范围传递为

https://graph.microsoft.com/User.Read openid profile offline_access
:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.