APIM 应用身份管理与授权最佳实践(使用 Microsoft Entra ID + Client Credentials Flow)
在微服务和企业级 API 管理场景中,如何安全、统一地管理后端 API 的访问身份和授权,是一个核心挑战。本文分享一种成熟的设计方案:通过 Azure API Management (APIM) 统一代理所有 API,并使用 Microsoft Entra ID(原 Azure AD) 集中管理所有消费应用的身份认证与授权。
整体设计思路
- 所有需要被保护的 API 均通过 APIM 进行代理和暴露。
- 任何调用 API 的应用(客户端/服务)均使用 Entra ID App Registration 进行身份注册。
- 采用 Client Credentials Flow(应用到应用的无用户认证模式)获取 JWT Access Token。
- APIM 在入口处使用
<validate-azure-ad-token>策略对 Token 进行严格校验。 - 授权逻辑基于 Entra ID 中的应用角色(App Roles) 实现,实现细粒度权限控制。
这种设计实现了身份集中管理、安全解耦和易于运维的目标。
Entra ID 中的应用注册与角色设计
所有配置均在 Microsoft Entra admin center(entra.microsoft.com)中完成。
1. 在 APIM 网关对应的 App Registration 上定义角色(推荐做法)
- App Registration 名称示例:abc-int-apigw(或 apim-backend-api)
- 在该应用中定义 App Roles(应用角色):
- 示例:
demoApp01-Role - 类型选择 Application(因为使用的是 client credentials flow)
- 示例:
为什么角色定义在网关/后端 API 的 App Registration 上?
因为这是 Token 的 Audience(受众)所属的应用,只有该应用才能暴露角色并让 Token 携带这些角色信息。
2. 在客户端应用(Client App)中授予权限
- App Registration 名称示例:demoApp01
- 进入 API permissions → Add a permission → My APIs
- 选择上面定义角色的应用(abc-int-apigw 或 apim-backend-api)
- 选择 Application permissions,勾选
demoApp01-Role - 完成 Grant admin consent for [Tenant](管理员同意)
3. 使用 Client Credentials Flow 获取 Token
curl --request POST \
--url https://login.microsoftonline.com/fffffcf9-5044-49a6-9935-fc23fc1b43c2/oauth2/v2.0/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data grant_type=client_credentials \
--data client_id=66bf753e-ffff-4963-bd77-c4f2fac14e7f \
--data 'client_secret=WcI8Q~k9CgMC3uaUy2HpnQY6narD_AWvMCpr5dyi' \
--data scope=api://6da34051-a52b-ffff-8b59-50c5a4630bde/.default
关键点:
scope 必须使用 abc-int-apigw(或对应后端 API)的 Application ID URI + /.default。
返回的 Token 中会包含 "roles": ["demoApp01-Role"]。
APIM 中的 Token 校验配置
1. 基础 API 调用(带 Subscription Key)
curl --request GET \
--url https://abc-int-apigw.azure-api.net/test \
--header 'Ocp-Apim-Subscription-Key: 5970de966fca496e84214e7ade9fc6ba'
(也可自定义 Header 为 X-API-KEY 等)
2. 推荐的 Inbound 策略(优化版)
<inbound>
<base />
<validate-azure-ad-token
tenant-id="fffffcf9-5044-49a6-9935-fc23fc1b43c2"
header-name="Authorization"
require-scheme="Bearer"
failed-validation-httpcode="401"
failed-validation-error-message="Unauthorized. Missing or invalid Azure AD token with required role.">
<!-- 支持两种常见的 audience 格式(推荐) -->
<audiences>
<audience>api://6da34051-a52b-ffff-8b59-50c5a4630bde</audience>
<audience>6da34051-a52b-ffff-8b59-50c5a4630bde</audience>
</audiences>
<!-- 强制要求应用角色 -->
<required-claims>
<claim name="roles" match="any">
<value>demoApp01-Role</value>
</claim>
</required-claims>
</validate-azure-ad-token>
</inbound>
改进建议:
- 使用 Named Values 管理
tenant-id、audience和角色名称,便于多环境切换(Dev/Test/Prod)。 - 可进一步添加
<on-error>策略,实现更友好的自定义错误消息(区分 audience 错误 vs 角色缺失)。
3. 带 Token 的完整调用示例
curl --request GET \
--url https://abc-int-apigw.azure-api.net/test \
--header 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6IlUxc1g4WUZIUzdaNlZsN1ZITEl6VGVqYnZqMCIsImtpZCI6IlUxc1g4WUZIUzdaNlZsN1ZITEl6VGVqYnZqMCJ9...' \
--header 'X-API-KEY: 5970de966fca496e84214e7ade9fc6ba'
成功响应示例:
{
"sampleField": "test"
}
使用不正确角色(或缺少角色)的 Token 时,返回:
{
"statusCode": 401,
"message": "Unauthorized. Missing or invalid Azure AD token with required role."
}
最佳实践总结
- Audience 配置:同时支持
api://GUID和纯 GUID 两种格式,避免常见校验失败。 - 角色类型:Client Credentials Flow 必须使用 Application 类型的 App Roles。
- 安全性:始终保留 Audience 检查;建议结合 Subscription Key + JWT 双重保护。
- 可维护性:优先使用 APIM Named Values + Policy Fragments。
- 错误处理:通过
failed-validation-error-message或<on-error>提供清晰的提示信息。 - 权限授予:务必执行 Admin Consent,否则 Token 中不会出现角色。
这种架构已在多个企业项目中验证有效,实现了统一身份管理、细粒度授权和高安全性的平衡。