c# - 使用 AAD 身份验证从带有 MSI 的应用服务向另一个应用服务 API 发出 HTTP 请求

标签 c# azure authentication azure-active-directory azure-web-app-service

我想要做的是使用 MSI 身份从应用服务 1 (MainWebApp) 向应用服务 2 (AadAuthenticationApiOne - Dev) 进行授权调用来自应用服务 1,它应该在应用服务 2 上获得授权。

虽然这应该不会太难,但我仍然无法让这个流程正常工作。可能是因为我在某处缺少一些复选框。我尝试了多种方法,但通过遵循 Joonas Westlin's blogpost on the matter 再次开始干净。

这意味着我有一个 MainWebApp 的身份(对象 ID:bf00c7e8-b14b-4fe5-b768-da255026ff17)和我的第二个应用服务的应用注册,名为 AadAuthenticationApiOne(对象 ID - 9863b99a-6f28-4053-8a47-050f2b6da1e7/应用程序 ID - 905ceb2e-8bde-48ca-bcbd-937b0ed30e67)

如博文中所述,我向应用程序注册添加了一个应用程序角色。只是为了尝试,我复制粘贴了他帖子中的完整 block ,以查看我是否可以正常工作。

{
  "appRoles": [
    {
      "allowedMemberTypes": [
        "Application"
      ],
      "displayName": "Read all things",
      "id": "32028ccd-3212-4f39-3212-beabd6787d81",
      "isEnabled": true,
      "description": "Allow the application to read all things as itself.",
      "value": "Things.Read.All"
    }
  ]
}

之后,我通过运行以下脚本向我的 MSI 添加了新的角色分配。

New-AzureADServiceAppRoleAssignment `
    -ObjectId bf00c7e8-b14b-4fe5-b768-da255026ff17 `
    -Id 32028ccd-3212-4f39-3212-beabd6787d81 `
    -PrincipalId bf00c7e8-b14b-4fe5-b768-da255026ff17 `
    -ResourceId 9863b99a-6f28-4053-8a47-050f2b6da1e7

为了从我的 MainWebApp 获取访问 token ,我运行了以下代码。

var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("905ceb2e-8bde-48ca-bcbd-937b0ed30e67", "b1f8cb55-7d7a-4e8d-9641-51372b423357");
// And I also tried the following
var azureServiceTokenProvider = new AzureServiceTokenProvider();
string accessToken = await azureServiceTokenProvider.GetAccessTokenAsync("https://[mine].onmicrosoft.com/6c14b806-7fec-4423-88e9-ce535e07787a");

这两种方式都会生成有效的 JWT,这对于以下示例来说看起来很熟悉。

{
  "aud": "905ceb2e-8bde-48ca-bcbd-937b0ed30e67",
  "iss": "https://sts.windows.net/b1f8cb55-7d7a-4e8d-9641-51372b423357/",
  "iat": 1574427342,
  "nbf": 1574427342,
  "exp": 1574456442,
  "aio": "42VgYHjp+2hqNdcyiVLGhlfLNFomAAA=",
  "appid": "a4e07406-b556-4c4d-9525-5f410fd21fe7",
  "appidacr": "2",
  "idp": "https://sts.windows.net/b1f8cb55-7d7a-4e8d-9641-51372b423357/",
  "oid": "bf00c7e8-b14b-4fe5-b768-da255026ff17",
  "roles": [
    "Things.Read.All"
  ],
  "sub": "bf00c7e8-b14b-4fe5-b768-da255026ff17",
  "tid": "b1f8cb55-7d7a-4e8d-9641-51372b423357",
  "uti": "FrqIC0box0imFrEVC1ZHAA",
  "ver": "1.0"
}

但是,在调用 API 时,我收到一个页面,提示登录您的帐户。 调用API的代码

_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var response = await _httpClient.GetAsync("https://myaadauthapi.azurewebsites.net/api/data");

API Controller 中的方法如下所示

[Authorize(Roles = "Things.Read.All")] //<-- Tried this one first, but didn't work
// [Authorize] // <-- Fallen back to this one, but didn't work either.
public IEnumerable<string> Get()
{
    return new[]
    {
        "One",
        "Een",
        "1",
        "Uno"
    };
}

当调用分配有 [AllowAnonymous] 属性的端点时,我从端点获得了预期结果。

我的猜测是,我在 API 中的配置不正确(或者 Azure 中的某些配置不正确)。

// The additions I did in the ConfigureServices method in Startup class
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
    .AddAzureAD(options =>
    {
        Configuration.Bind("AzureAd", options);
    });

// And of course the addition to the Configure method
app.UseAuthentication();

当然还有应用程序设置

"AzureAd": {
  "Instance": "https://login.microsoftonline.com/",
  "CallbackPath": "/signin-oidc",
  "Domain": "[mine].onmicrosoft.com",
  "TenantId": "b1f8cb55-7d7a-4e8d-9641-51372b423357",
  "ClientId": "905ceb2e-8bde-48ca-bcbd-937b0ed30e67"
},

为了更好地衡量,我还将 MainWebApp 作为所有者添加到 AadAuthenticationApiOneMainWebApp assigned as Owner to AadAuthenticationApiOne - Access Control

最佳答案

您似乎已在 API 上使用 OpenID Connect 配置了 Azure AD 身份验证。这不是正确的方法。应使用 Azure AD Bearer token 身份验证配置 API。它不重定向请求,它需要访问 token 。我也有关于该设置的文章;)

https://joonasw.net/view/azure-ad-authentication-aspnet-core-api-part-1

关于c# - 使用 AAD 身份验证从带有 MSI 的应用服务向另一个应用服务 API 发出 HTTP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58995454/

相关文章:

azure - 如何查找谁在Azure Portal的Keyvault中创建/编辑了 secret ?

azure - 使用 Azure 数据工厂检索 CRM D365 选项集字段数据时出现问题

ssl - 支持带 ELB 的双向 TLS/HTTPS

c# - 如何在不在 Visual Studio 中打开其关联解决方案的情况下打开项目?

c# - 是否可以使用 Blob 分析删除图像的小块?

c# - MySqlException : Data too long for column 'Id' at row 1

azure - 如何在 Azure DevOps 中构建多个相互依赖的 Visual Studio 解决方案

authentication - 当对 WildFly 中部署的 war 使用基本身份验证时,getUserPrincipal 返回 null

Java EWS 与单个(管理员)用户集成

c# - 是否可以取消 Sql Bulk Copy.Write To Server (c#)?