MSAL Python OBO授权流报错AADSTS90014:凭据中缺少必填字段'iss'
MSAL Python OBO授权流报错AADSTS90014:凭据中缺少必填字段'iss'
我太懂你这种调试到头疼的感觉了——明明JWT里明明有iss字段,客户端应用初始化也没报错,偏偏OBO流就是报“iss缺失”,而且搜遍了帖子都找不到同款问题。结合你的代码和场景,我梳理了几个大概率能解决问题的方向,咱们一个个来排查:
1. 最可能的原因:OBO调用的参数格式完全错误
你的代码里直接把去掉Bearer 的token字符串传给了acquire_token_on_behalf_of,但MSAL Python的这个方法第一个参数要求是包含assertion键的字典,不是直接传token字符串!
虽然JWT本身有iss字段,但因为你传参格式不对,MSAL没办法正确解析这个token,才会抛出“iss缺失”的错误(这个报错确实有点误导人)。
代码修改建议
把你的OBO调用代码改成这样:
@app.route("test", methods=[func.HttpMethod.GET], auth_level=func.AuthLevel.ANONYMOUS) def leads(req: func.HttpRequest) -> func.HttpResponse: authorization: str = req.headers.get("Authorization") # type: ignore if not authorization or not authorization.startswith("Bearer "): return func.HttpResponse("Missing or invalid Authorization header", status_code=401) ua = authorization.removeprefix("Bearer ") scopes = ["https://sql.azuresynapse-dogfood.net/user_impersonation"] # 关键修正:用字典包裹assertion,而不是直接传token字符串 obo_params = { "assertion": ua, "requested_token_use": "on_behalf_of" # 可选,但能明确指定OBO用途 } result = msal_app.acquire_token_on_behalf_of(obo_params, scopes) if "access_token" not in result: body = {"result": result} return func.HttpResponse(json.dumps(body), status_code=500) else: return func.HttpResponse(json.dumps({"result": "success"}), status_code=200, mimetype="application/json")
2. 验证证书与私钥的匹配性(虽然初始化没报错,但不能掉以轻心)
你提到重新生成了证书,虽然ConfidentialClientApplication初始化没报错,但还是要确认:
- 上传到Entra ID App Registration的
server.crt,和函数app环境变量里的私钥是同一对儿生成的 - 环境变量里的私钥格式是否正确:要确保包含完整的
-----BEGIN PRIVATE KEY-----和-----END PRIVATE KEY-----标记,并且换行符没有被吃掉(有些云环境的环境变量会自动去掉换行,导致私钥失效,这种情况初始化时可能不报错,但实际调用OBO时就会出问题)
如果怀疑私钥格式有问题,可以临时在代码里打印私钥内容(测试用,别上线),对比本地的私钥文件,确保完全一致。
3. 检查前端请求的Scopes是否符合OBO流要求
你的前端用的是${CLIENT_ID}/.default作为scope,这个scope是用来获取前端自己的客户端凭证流token的,而OBO流需要的是前端获取的token必须是发给后端API的委托token。
具体来说:
- 你的后端App Registration需要暴露一个API(在Entra ID的App Registration里,找到“暴露API”选项卡,设置API ID URI,比如
api://backend-client-id) - 前端App Registration需要添加这个后端API的委托权限(在“API权限”里添加,找到你后端的App Registration,勾选对应的委托权限,比如
user_impersonation) - 前端请求的scope要改成后端API的ID URI + 权限,比如
api://backend-client-id/.default或者api://backend-client-id/user_impersonation
这样前端获取的token才是专门发给后端的,后端才能用这个token成功执行OBO流。
最后总结
先优先修改第一个点——把token用字典包裹传给OBO方法,这是最有可能解决你当前报错的原因。如果改完还是有问题,再依次排查证书匹配性和前端scope的问题。
内容来源于stack exchange
相关产品推荐
相关产品推荐

