【问题标题】:Azure AD: Call .net Core Web API from other .net Core Web APIAzure AD:从其他 .net Core Web API 调用 .net Core Web API
【发布时间】:2020-02-07 23:13:20
【问题描述】:

我有一种情况,我们使用 .net Core Web API 来管理一些“机器”。 公开的 API 之一是模拟此类机器的操作。 这些机器有不同的版本,每个不同的版本都有不同的内部行为,但界面相同。

然后,我们开发了一系列不同的 .net Core Web API 来模拟每个不同版本的机器。

因此我需要从 API 调用 API,这听起来很简单,因为我已经在使用 Microsoft Graph

在 startup.cs 中,我有:

public void ConfigureServices(IServiceCollection services)
{
    // To protect the API with Azure AD
    services
        .AddProtectedWebApi(Configuration);

    // To have ITokenAcquisition when calling the specific simulation API
    services
        .AddMicrosoftIdentityPlatformAuthentication(Configuration)
        .AddMsal(Configuration, new string[] { Configuration["SimulationAPIv411:Scope"] })
        .AddInMemoryTokenCaches();

考虑到这一流程,我正在使用 Postman 对其进行测试:

  1. 我通过 Postman 获得了一个不记名令牌以访问通用 API
  2. Postman 在通用 API 中调用 SimulationDispatcherController
  3. SimulationDispatcherController 调用具体的模拟 API
  4. 结果流回 Postman

我正在经历的是:

  1. 如果我这样离开,在邮递员中我会得到一个登录页面

    <!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
    <!DOCTYPE html>
    <html dir="ltr" class="" lang="en">
    
    <head>
        <title>Sign in to your account</title>
    [...]
    
  2. 如果我删除 .AddMicrosoftIdentityPlatformAuthentication(Configuration) 行,那么我可以到达 SimulationDispatcherController,但是当它尝试调用其他 API 时,我得到了错误:

    MSAL.NetCore.4.8.1.0.MsalUiRequiredException: 
    ErrorCode: user_null
    Microsoft.Identity.Client.MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call.
    [...]
    

    我尝试使用ITokenAcquisition 对象获取令牌,调用GetAccessTokenOnBehalfOfUserAsync(_Scopes);,其中范围是特定API 所需的范围。

您是否有任何建议或文档链接可以更好地解释如何在受 Azure AD 保护的 API 中配置 MSAL?

编辑: 正如答案中所建议的,唯一需要的更改是:

.AddMsal(Configuration, new string[] { Configuration["SimulationAPIv411:Scope"] })

.AddProtectedApiCallsWebApis(Configuration)

【问题讨论】:

    标签: c# asp.net-core azure-active-directory msal


    【解决方案1】:

    如果要从 Azure AD 投射的其他 .net Core Web API 调用 .net Core Web API,请使用 OAuth 2.0 On-Behalf-Of flow。详细步骤如下

    1. 在客户端应用程序中登录用户
    2. 获取 Web API A 的令牌并调用 它。
    3. Web API 然后调用另一个下游 Web API B(我使用 Microsoft 用于测试的图表)。

    关于如何配置,请参考以下步骤:

    注册 web api 应用

    1. Register APP
    2. 创建客户端密码
    3. Configure permissions to access another web api。 (我使用 Microsoft graph 进行测试)
    4. Configure an application to expose web APIs(添加 api 作用域)

    注册客户端应用

    1. Register APP
    2. 创建客户端密码
    3. Configure permissions to access web API

    为 Web API 应用程序配置已知客户端应用程序

    1. 在 Azure 门户中,导航到您的 Web api 应用注册,然后点击 Manifest 部分。

    2. 找到属性 knownClientApplications 并添加客户端应用程序的客户端 ID

    配置项目

    1. 将引用 Microsoft.Identity.Web 添加到您的项目中

    2. 在appsettings.json中添加如下代码

    {
      "AzureAd": {
        "Instance": "https://login.microsoftonline.com/",
        "TenantId": "<your tenant id>",
        "ClientId": "<app id of Web API A>",
        "ClientSecret": "<app secret of Web API A>"
      },
    
    1. 在stratup.cs中添加以下代码
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddProtectedWebApi(Configuration)
                       .AddProtectedApiCallsWebApis(Configuration)
                       .AddInMemoryTokenCaches();
    
    1. 控制器
    [Authorize]
        [ApiController]
        [Route("[controller]")]
        public class WeatherForecastController : ControllerBase
        {
                  private readonly ITokenAcquisition _tokenAcquisition;
            private readonly ILogger<WeatherForecastController> _logger;
    
            public WeatherForecastController(ILogger<WeatherForecastController> logger, ITokenAcquisition tokenAcquisition)
            {
                _logger = logger;
                _tokenAcquisition = tokenAcquisition;
            }
    
    
    
            [HttpGet]
            public async Task<string> Get()
            {
    
                string[] scopes = { "user.read" }; // the scope of Web API B
                string accessToken = await _tokenAcquisition.GetAccessTokenOnBehalfOfUserAsync(scopes);
                // you use the accessToken to call the Web API B
                GraphServiceClient client = new GraphServiceClient(new DelegateAuthenticationProvider(
                        async (requestMessage) =>
                        {
                            requestMessage.Headers.Authorization =
                                new AuthenticationHeaderValue("Bearer", accessToken);
                        }));
    
                User user =await client.Me.Request().GetAsync();
                return user.UserPrincipalName;
            }
    
         }
    

    在邮递员中测试

    1. 获取 Web API A 的访问令牌

    2. 调用 Web API A,然后让 Web API A 调用 Microsoft 图形

    更多详情请参考documentsample

    【讨论】:

    【解决方案2】:

    看来其他特定的模拟 API 也受 Azure AD 保护,您可以使用OAuth 2.0 On-Behalf-Of flow,它适用于应用程序调用服务/Web API 的场景,而后者又需要调用另一个服务/Web API。

    Here 是在 MSAL 2.3 及更高版本的 asp.net core web api 中使用 OBO 流的代码示例。

    【讨论】:

      猜你喜欢
      • 2019-03-14
      • 2019-05-30
      • 2021-09-24
      • 2018-05-08
      • 2021-10-13
      • 2020-06-27
      • 2020-06-28
      • 2020-03-09
      • 2020-11-13
      相关资源
      最近更新 更多