使用 Azure AD 通过 OAuth2 对 Azure API 管理进行身份验证

Authenticate Azure API Management with OAuth2 using Azure AD

我正在尝试通过阅读以下文章通过 AzureAD 使用 OAuth2 保护 APIM APIs:Protect a web API backend in Azure API Management by using OAuth 2.0 authorization with Azure AD

AzureAPIM - OAuth2

AzureAD - backend-app:

AzureAD - client-app:

对于演示会议 API,将验证 JWT 策略添加到入站处理,其中 3a0cf09b- 是租户 ID,b7c31179- 是 backend-app 应用程序 ID:

在开发人员门户中,使用 return 令牌对 AzureAD 的身份验证成功:

但是调用 API 授权失败:

检查 jwt.io 中收到的令牌,我发现 "aud": "00000003-0000-0000-c000-000000000000" 不是 backend-app 应用程序 ID:

{
  "aud": "00000003-0000-0000-c000-000000000000",
  "iss": "https://sts.windows.net/3a0cf09b-xxx/",
  "app_displayname": "client-app",
  "appid": "05a245fb-xxx",
  "scp": "Files.Read User.Read profile openid email",
  "tenant_region_scope": "OC",
  "tid": "3a0cf09b-2952-4673-9ace-0e1bf69ee23a",
  "unique_name": "user1@xxx.onmicrosoft.com",
}

API 测试 HTTP 响应跟踪显示 validate-jwt:

上的错误
validate-jwt (-0.138 ms)
{
    "message": "JWT Validation Failed: Claim value mismatch: aud=b7c31179-xxx.."
}

用令牌 00000003-0000-0000-c000-000000000000 中的值替换 aud 或删除 validate-jwt 策略中的 required-claims 以使其正常工作。

有什么想法吗?

从你的报错来看,确实是401错误,就是你的aud和你要调用的api不匹配,我用的是auth code flow做的简单演示给大家:

首先公开back-end应用的api,添加客户端应用。

接下来,在 'API permissions' 下,为您的 front-end 应用程序授予对后端 api 的访问权限:

  • 在 'API permissions' 下单击 'Add permission',然后单击 'My APIs' 选项卡。
  • 找到您的后端应用程序和select适当的范围。
  • 点击'Add permissions'。
  • 为您的 API 授予管理员许可。

获取令牌:

解析token:

您似乎选择了 OAuth2 授权的 v1 端点而不是 v2 端点,因此访问令牌中 aud 的值应该像 b7c31179-xxxx.... 而不是 api://b7c31179-xxxx....。所以你获取access token的步骤没有错误。

根据我这边的一些测试,这个问题的原因是你在你的APIM中配置OAuth2.0时没有指定一个参数resource为backend-app application id的值。你提到的 document 也提到了这个(我测试没有指定这个参数,它表明你的问题相同)

因此,要解决此问题,请转到您的 APIM 并单击“OAuth 2.0”选项卡,编辑您创建的项目。添加参数 resource,值为后端应用程序 ID。

注意:当您添加参数resource并点击“保存”按钮时,请再次打开该项目并检查“Client secret”框是空的。当我在我这边测试时,“Client secret”框在添加参数 resource 后显示为空,这可能是该页面上的错误。如果“Client secret”为空,当您在 Developer portal 中获取访问令牌时,它可能会显示类似 The request body must contain the following parameter: 'client_assertion' or 'client_secret' 的错误消息。