使用 Microsoft Entra ID(Azure AD)为 M2M 请求授权
Microsoft Entra ID 的前身是 Azure Active Directory,是 Microsoft 提供的云端身份与访问管理服务。除了对用户进行身 份认证,它还可以向应用颁发访问 Token,使后台服务、计划任务和自动化程序无需最终用户登录即可调用 API。
OAuth 2.0 客户端凭证流程专为此类机器到机器(M2M)通信而设计。Apache APISIX 可以在代理请求前验证每个 Token 的签名、颁发者、受众和所分配的应用权限,从而保护目标 API。
本指南介绍如何为此 M2M 场景配置 Microsoft Entra ID 和 APISIX。一个 Microsoft Entra 应用代表受保护的 API,另一个代表调用服务。调用服务获得应用权限,并使用客户端密钥请求访问 Token。APISIX 使用 Microsoft Entra ID 的 JSON Web Key Set(JWKS)在本地验证 Token,并在将请求转发到示例上游之前移除身份认证数据。
前置条件
- 安装 Docker。
- 安装 cURL 和 jq。
- 按照入门指南使用 Docker 启动 APISIX。
- 拥有 Microsoft Entra 租户的访问权限,以及注册应用、创建应用角色和授予租户级管理员同意的权限。Cloud Application Administrator 或权限更高的角色即可满足要求。
- 如果计划使用 ADC,请先安装并配置 ADC。
配置 Microsoft Entra ID
分别为受保护的 API 和 M2M 客户端创建应用注册。这样,Microsoft Entra ID 就能为正确的 API 受众颁发 Token,并且只包含授予该客户端的应用权限。
注册受保护的 API
登录 Microsoft Entra 管理中心,注册代表受保护 API 的应用:
- 选择 Entra ID → App registrations → New registration。
- 输入
APISIX Protected API作为应用名称。 - 在 Supported account types 下选择 Single tenant only。
- 将 Redirect URI 留空,因为此应用不用于用户登录。
- 选择 Register。
在应用的 Overview 页面记录 Application (client) ID 和 Directory (tenant) ID。
添加应用角色
为受保护的 API 配置标识符:
- 选择 Expose an API。
- 在 Application ID URI 旁选择 Add。
- 接受生成的
api://<application-client-id>值。 - 选择 Save。
接下来,创建用于授予 API 访问权限的应用角色:
-
选择 App roles → Create app role。
-
配置角色:
- Display name:
Access APISIX API - Allowed member types:
Applications - Value:
access_as_application - Description:
Access the API protected by APISIX - Do you want to enable this app role?:选中
- Display name:
-
选择 Apply。

配置版本 2 访问 Token
将受保护的 API 配置为接收版本 2 访问 Token:
- 选择 Manifest。
- 在
api对象中找到requestedAccessTokenVersion。 - 将其值从
null改为2。 - 选择 Save。
此设置使 Microsoft Entra ID 为该受保护 API 颁发版本 2 访问 Token。本示例需要此设置,因为 APISIX 会根据特定于租户的版本 2 颁发者和受众格式验证 Token。
注册 M2M 客户端
返回 App registrations,创建用于调用受保护 API 的应用:
- 选择 New registration。
- 输入
APISIX M2M Client作为应用名称。 - 在 Supported account types 下选择 Single tenant only。
- 将 Redirect URI 留空,因为此应用不用于用户登录。
- 选择 Register。
在应用的 Overview 页面记录 Application (client) ID。
创建客户端密钥
创建供 M2M 客户端请求访问 Token 的凭证:
- 在 M2M 客户端应用中选择 Certificates & secrets。
- 选择 Client secrets → New client secret。
- 输入说明,并选择符合组织凭证轮换策略的有效期。
- 选择 Add。
立即复制客户端密钥的 Value。Microsoft Entra ID 只显示一次该值。Secret ID 不是客户端密钥。
本示例使用客户端密钥进行本地测试。对于生产应用,Microsoft 建议改用证书凭证或工作负载身份联合。
授予应用权限
将受保护 API 的应用角色分配给 M2M 客户端:
- 在 M2M 客户端应用中选择 API permissions → Add a permission。
- 选择 My APIs → APISIX Protected API。
- 选择 Application permissions。
- 选择 Access APISIX API。
- 选择 Add permissions。
如果受保护的 API 未出现在 My APIs 下,请将当前管理员添加为两个应用注册的所有者,然后重试。
为应用权限授予租户级同意:
- 选择 Grant admin consent for,然后选择租户名称。
- 确认操作。
权限状态应显示 Granted for,后面跟同一租户名称。

Microsoft Entra ID 还可能显示自动添加的 Microsoft Graph User.Read 委托权限。此 M2M 流程不会使用它。
将租户 ID、受保护 API 的客户端 ID、M2M 客户端 ID、M2M 客户端密钥和相关值保存到环境变量中,并替换示例 值:
export ENTRA_TENANT_ID=replace-with-your-tenant-id
export ENTRA_API_CLIENT_ID=replace-with-your-protected-api-client-id
export ENTRA_M2M_CLIENT_ID=replace-with-your-m2m-client-id
export ENTRA_M2M_CLIENT_SECRET=replace-with-your-m2m-client-secret
export ENTRA_DISCOVERY="https://login.microsoftonline.com/${ENTRA_TENANT_ID}/v2.0/.well-known/openid-configuration"
export ENTRA_API_ID_URI="api://${ENTRA_API_CLIENT_ID}"
配置 APISIX
配置一条路由,在将请求转发到公共 HTTP 请求与响应服务 httpbin.org 之前接受 Microsoft Entra ID Bearer Token。/anything/m2m/* 端点会返回请求详情以供验证。
选择使用 Admin API 或 ADC 配置路由。
- Admin API
- ADC
创建一条使用 Microsoft Entra ID 的 JWKS 在本地验证 Bearer Token 的路由:
curl "http://127.0.0.1:9180/apisix/admin/routes/entra-m2m" -X PUT \
--data-binary @- <<EOF
{
"uri": "/anything/m2m/*",
"plugins": {
"openid-connect": {
"client_id": "$ENTRA_API_CLIENT_ID",
"discovery": "$ENTRA_DISCOVERY",
"bearer_only": true,
"use_jwks": true,
"claim_validator": {
"audience": {
"required": true,
"match_with_client_id": true
}
},
"claim_schema": {
"type": "object",
"properties": {
"roles": {
"type": "array",
"contains": {
"const": "access_as_application"
}
}
},
"required": ["roles"]
},
"set_access_token_header": false,
"set_id_token_header": false,
"set_userinfo_header": false
},
"proxy-rewrite": {
"headers": {
"remove": ["Authorization"]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}
EOF
discovery 的值是特定于租户的 Microsoft Entra ID 版本 2 OIDC 发现文档。APISIX 使用其中的颁发者和 JWKS 端点验证 Token。
❶ bearer_only:设置为 true,要求使用 Bearer 访问 Token,而不是启动交互式浏览器登录流程。
❷ use_jwks:设置为 true,使用 Microsoft Entra ID 发布的公钥在本地验证 JWT 签名。
❸ claim_validator.audience:要求 Token 的 aud 声明与配置为 client_id 的受保护 API 应用 ID 匹配。
❹ claim_schema:要求 Token 的 roles 声明包含已分配给 M2M 客户端的应用权限。
❺ set_access_token_header、set_id_token_header 和 set_userinfo_header:设置为 false,防止 APISIX 将访问 Token、ID Token 和 Token 声明添加到上游请求头。
❻ proxy-rewrite.headers.remove:在 APISIX 代理请求前移除原始 Bearer Token。如果上游应用必须接收访问 Token 或其声明,请复查这些请求头设置。
使用相同的路由配置创建 adc.yaml 文件:
services:
- name: httpbin
routes:
- name: entra-m2m
uris:
- /anything/m2m/*
plugins:
openid-connect:
client_id: "${ENTRA_API_CLIENT_ID}"
discovery: "${ENTRA_DISCOVERY}"
bearer_only: true
use_jwks: true
claim_validator:
audience:
required: true
match_with_client_id: true
claim_schema:
type: object
properties:
roles:
type: array
contains:
const: access_as_application
required:
- roles
set_access_token_header: false
set_id_token_header: false
set_userinfo_header: false
proxy-rewrite:
headers:
remove:
- Authorization
upstream:
type: roundrobin
nodes:
- host: httpbin.org
port: 80
weight: 1
discovery 的值是特定于租户的 Microsoft Entra ID 版本 2 OIDC 发现文档。APISIX 使用其中的颁发者和 JWKS 端点验证 Token。
❶ bearer_only:设置为 true,要求使用 Bearer 访问 Token,而不是启动交互式浏览器登录流程。
❷ use_jwks:设置为 true,使用 Microsoft Entra ID 发布的公钥在本地验证 JWT 签名。
❸ claim_validator.audience:要求 Token 的 aud 声明与配置为 client_id 的受保护 API 应用 ID 匹配。
❹ claim_schema:要求 Token 的 roles 声明包含已分配给 M2M 客户端的应用权限。
❺ set_access_token_header、set_id_token_header 和 set_userinfo_header:设置为 false,防止 APISIX 将访问 Token、ID Token 和 Token 声明添加到上游请求头。
❻ proxy-rewrite.headers.remove:在 APISIX 代理请求前移除原始 Bearer Token。如果上游应用必须接收访问 Token 或其声明,请复查这些请求头设置。
将配置同步到 APISIX:
adc sync -f adc.yaml
验证 M2M 授权
从 Microsoft Entra ID 为受保护的 API 请求访问 Token:
export ENTRA_ACCESS_TOKEN="$(
curl -sS "https://login.microsoftonline.com/${ENTRA_TENANT_ID}/oauth2/v2.0/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=${ENTRA_M2M_CLIENT_ID}" \
--data-urlencode "client_secret=${ENTRA_M2M_CLIENT_SECRET}" \
--data-urlencode "scope=${ENTRA_API_ID_URI}/.default" \
--data-urlencode "grant_type=client_credentials" | \
jq -er '.access_token'
)"
将访问 Token 发送到受保护的路由:
curl -i "http://127.0.0.1:9080/anything/m2m/get" \
-H "Authorization: Bearer ${ENTRA_ACCESS_TOKEN}"
返回 HTTP/1.1 200 OK 表示 APISIX 已接受为受保护 API 颁发且包含所需应用角色的 Token。响应正文应包含类似以下内容的字段:
{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "localhost",
"User-Agent": "curl/8.7.1",
"X-Amzn-Trace-Id": "Root=1-...",
"X-Forwarded-Host": "localhost:9080"
},
"json": null,
"method": "GET",
"origin": "192.168.155.1, xxx.xxx.xxx.xxx",
"url": "http://localhost:9080/anything/m2m/get"
}
请求头值和报告的源地址会因客户端及网络环境而异。由于路由阻止相关信息被代理 ,上游请求头不应包含 Authorization、X-Access-Token、X-Id-Token 或 X-Userinfo。
发送不带 Token 的相同请求:
curl -i "http://127.0.0.1:9080/anything/m2m/get"
由于该路由要求 Bearer Token,APISIX 应返回 HTTP/1.1 401 Unauthorized。
后续步骤
你已配置 APISIX,使用 Microsoft Entra ID 的访问 Token 和应用权限为 M2M 请求授权。如需配置基于浏览器的用户身份认证,请参阅使用 Microsoft Entra ID 配置 SSO。有关更多 Token 验证和授权选项,请参阅 openid-connect 插件参考。