Python Azure函数使用托管标识调用API的作用域配置疑问
问题根因
你判断“用函数自身APPLICATION_ID作为scope申请令牌不合理”是完全正确的。你现在代码能跑通,本质是你误把被调用API对应的AAD应用ID当成了函数自己的应用ID——AAD颁发服务调用token时,scope必须指向被调用的目标API对应的AAD注册资源,和调用方(你的Azure Function)的应用ID没有任何关系。
你换其他scope就报错是AAD的正常校验逻辑:所有申请token的scope必须提前在目标API的AAD应用注册中完成暴露和权限配置,未注册的scope会被AAD直接拒绝,不会颁发有效token。
标准配置流程
- 第一步:定位目标API的AAD注册对象
先找到你部署在App Service上的API开启AAD认证时关联的AAD应用注册,记录下它的「应用程序(客户端) ID」,记为API_APP_ID。如果当时开认证用的是快速配置模式,Azure会自动给API生成对应的AAD应用,直接用这个自动生成的应用的ID即可,不要额外新建AAD应用。 - 第二步:配置API的公开权限
进入该API对应的AAD应用注册页面,打开「公开API」配置项:- 确认应用ID URI配置正确,默认格式为
api://<API_APP_ID>,如果API绑定了自定义域名,也可以把应用ID URI改成和API访问根域名一致的格式。 - 添加服务调用需要的权限,服务到服务无用户场景直接配置应用权限即可,比如命名为
Api.Access。
- 确认应用ID URI配置正确,默认格式为
- 第三步:给函数托管标识授权
找到你的Azure Function使用的托管标识(系统分配/用户分配均可)对应的服务主体,进入「API权限」配置页,添加刚才在API应用注册里暴露的权限,配置完成后点击「授予管理员同意」,否则权限不会生效。 - 第四步:代码调整
申请token时的scope固定使用api://<API_APP_ID>/.default格式即可,这里的ID必须填被调用API的AAD应用ID,不要填函数自身的客户端ID。
参考实现代码
from azure.identity import DefaultAzureCredential import requests # 如果使用用户分配托管标识,初始化时需要传入参数 managed_identity_client_id="<用户分配托管标识的客户端ID>" credential = DefaultAzureCredential() # scope指向被调用API的资源 token = credential.get_token("api://<替换为你的API对应AAD应用ID>/.default") request_headers = { "Authorization": f"Bearer {token.token}", "Content-Type": "application/json" } # 发起API调用 resp = requests.get("https://<替换为你的App Service API域名>/接口路径", headers=request_headers) print(resp.status_code)
常见踩坑说明
.default后缀是服务到服务无交互场景的固定写法,代表申请该资源下已经给调用方授予的所有静态权限,不要随意替换成其他自定义后缀,否则会出现资源不匹配、权限不足的报错。- 如果配置完成后拿到token调用API返回401,先检查API侧的AAD认证配置里的合法受众(audience)是否和你申请token时用的应用ID URI一致,不一致的话API侧会判定token无效。
- 不要跨租户配置权限,函数托管标识和API的AAD应用必须在同一个Azure AD租户下,否则无法直接授予权限。
内容的提问来源于stack exchange,提问作者Alexolo
相关产品推荐
相关产品推荐

