如何使用 Azure Ad client_credentials 验证保护后端 Web api 以实现服务器到服务器的通信

How to authenticate protect a backend web api for server to server communication using Azure Ad client_credentials

我有一个 curl 脚本,它从 Azure AD 请求新的访问令牌。我需要它 return 我的 API 的某种声明,角色或范围都可以。

我可以获得一个访问令牌,但它不是 return角色声明或范围或任何类似性质的东西。

在网络中使用时API

services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)                 
   .AddMicrosoftIdentityWebApi(Configuration.GetSection("AzureAd"));

我得到:

Neither scope or roles claim was found in the bearer token.

我试过设置

"AllowWebApiToBeAuthorizedByACL" : true,

appsettings.json 中,但它并没有像预期的那样阻止错误的发生。

这用于在 curl 脚本和微服务之间进行授权。作为后台服务,没有用户 交互,它只是服务器到服务器授权。我只是想保护网络 api。因此,出于安全原因,我想确保创建的访问令牌实际上是该系统的访问令牌,这就是为什么我在我的应用程序中寻找某种声明或角色以确保它不仅仅是来自另一部分的随机访问令牌系统的。

没有角色或范围,我的应用程序抛出以下错误

System.UnauthorizedAccessException: IDW10201: Neither scope or roles claim was found in the bearer token.

Oauth2 使用范围使用户能够授予客户端访问其数据的权限,因为这不需要我不认为我在寻找她的是范围。我认为我需要的是一种为应用程序本身定义角色的方法。我对天蓝色的经验很少,所以如果我错了请纠正我。

curl 脚本

curl -X POST -d "grant_type=client_credentials&client_id=api://a4994a31-c494-4b73-9622-d3a7144abeee&client_secret=[secret]&resource=api://a4994a31-c494-4b73-9622-d3a7144abeee" https://login.microsoftonline.com/1e2ad6d6-274f-43e8-89ef-d36d65bb83b5/oauth2/token

回应

    {
      "aud": "api://a4994a31-c494-4b73-9622-d3a7144abee",
      "iss": "https://sts.windows.net/1e2ad6d6-274f-43e8-89ef-d36d6583b5/",
      "iat": 1628506854,
      "nbf": 1628506854,
      "exp": 1628510754,
      "aio": "E2ZgYChZ8/PRc/eJ5sYfulfVXWUrBQA=",
      "appid": "a4994a31-c494-4b73-9622-d3a7144abeee",
      "appidacr": "1",
      "idp": "https://sts.windows.net/1e2ad6d6-274f-43e8-89ef-d36d65bb835/",
      "oid": "81f74198-ab14-4b0b-bad6-62893e15f9c8",
      "rh": "0.AQsA1tYqHk8n6EOJ79NtZbuDtTFKmaSUxHNLliLTpxRKvu4AAA.",
      "sub": "81f74198-ab14-4b0b-bad6-62893e15f9c",
      "tid": "1e2ad6d6-274f-43e8-89ef-d36d65bb83b",
      "uti": "FaZGzuuRn0eEQYPRReoYAQ",
      "ver": "1.0"
    }

我尝试设置范围

然后将其添加到 curl 脚本中

curl -X POST -d "grant_type=client_credentials&client_id=api://a4994a31-c494-4b73-9622-d3a7144abeee&client_secret=[Secret]&resource=api://a4994a31-c494-4b73-9622-d3a7144abeee&scope=api://a4994a31-c494-4b73-9622-d3a7144abeee/load_scope" https://login.microsoftonline.com/1e2ad6d6-274f-43e8-89ef-d36d65bb83b5/oauth2/token

没有任何影响,访问令牌仍然不包含任何范围。

然后我尝试添加一个角色

add 将角色添加到资源

curl -X POST -d "grant_type=client_credentials&client_id=api://a4994a31-c494-4b73-9622-d3a7144abeee&client_secret=[secret]&resource=api://a4994a31-c494-4b73-9622-d3a7144abeee/load" https://login.microsoftonline.com/1e2ad6d6-274f-43e8-89ef-d36d65bb83b5/oauth2/token

但这只是 return 一个错误

{"error":"invalid_resource","error_description":"AADSTS500011: The resource principal named api://a4994a31-c494-4b73-9622-d3a7144abeee/load was not found in the tenant named 1e2ad6d6-274f-43e8-89ef-d36d65bb83b5. This can happen if the application has not been installed by the administrator of the tenant or consented to by any user in the tenant. You might have sent your authentication request to the wrong tenant.

清单

我目前正在关注Assign app roles to applications这是清单。

"appId": "51bdea30-a886-47f7-a27f-994c8caca5c",
    "appRoles": [
        {
            "allowedMemberTypes": [
                "Application"
            ],
            "description": "myapprole",
            "displayName": "myapprole",
            "id": "bdaa8bc7-e0b3-47b1-b92-9011313e16ae",
            "isEnabled": true,
            "lang": null,
            "origin": "Application",
            "value": "myapprole"
        }
    ],

解决方案是添加 AllowWebApiToBeAuthorizedByACL 这会删除错误消息并允许后端服务在不需要角色或声明的情况下进行通信。

System.UnauthorizedAccessException: IDW10201: Neither scope or roles claim was found in the bearer token.

我已经添加了它,但是在深入研究了 Microsoft.Identity.Web 的源代码后它并没有工作。我发现我使用的是旧版本 Microsoft.Identity.Web 这显然是在添加 AllowWebApiToBeAuthorizedByACL 检查之前。我删除了 NuGet 包并在 1.15.2 重新添加它并且它有效。

 "AzureAd": {
    "Instance": "https://login.microsoftonline.com/",
    "Domain": "[Redacted]",
    "ClientId": "[Redacted]",
    "TenantId": "[Redacted]",
    "AllowWebApiToBeAuthorizedByACL" : true,
    "CallbackPath": "/signin-oidc"
  },