You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI集成Azure EntraID认证调用API遇scope问题,求解决方案

问题分析与解决方案

你的核心问题在于客户端凭证(client_credentials)模式下,Azure Entra ID 不支持直接指定自定义委派权限 scope,且该模式生成的令牌中,应用权限会放在roles声明而非scope声明里,导致原API的validate_scope验证逻辑失效。以下是具体解决步骤:

一、修正Azure Entra ID应用配置

  1. 进入Azure Portal的Entra ID控制台,找到你的API应用注册
  2. 切换到API权限页面,点击「添加权限」→「我的API」,选择当前API应用
  3. 选择应用权限(而非委派权限,因为client_credentials是无用户的服务间调用模式),添加名为access_api的权限(与你代码中的scope值一致)
  4. 点击「授予管理员同意」(必须完成此步骤,否则客户端无法获取权限)

二、修改API验证逻辑

原代码的validate_scope是针对委派权限的验证逻辑,不适用于客户端凭证模式的应用权限。需替换为角色验证:

from fastapi import APIRouter,Request
from fastapi_microsoft_identity import AuthError,requires_auth,validate_roles
import fastapi
from fastapi.exceptions import HTTPException
from pydantic import ValidationError
from utills.config import AppConfigs


poc_router = APIRouter()
required_role = "access_api"


@poc_router.get("/add/{num1}/{num2}")
@requires_auth
async def add_with_auth(request:Request,num1:int,num2:int):
    try:
        # 替换validate_scope为validate_roles,验证应用权限
        validate_roles(required_roles=[required_role], request=request)
        return num1+num2
    except AuthError as ae:
        return fastapi.Response(content=ae.error_msg, status_code=ae.status_code)
    except ValidationError as ve:
        return fastapi.Response(content=str(ve), status_code=400)
    except Exception as e:
        raise HTTPException(status_code=403,detail=f"Failed with Exception--{str(e)}")

三、保留令牌获取代码(无需修改)

客户端凭证模式下,必须使用api://{CLIENT_ID}/.default作为scope,它会自动包含所有已授予该客户端的应用权限。你的令牌获取代码是正确的:

from utills.config import AppConfigs
import subprocess,json
def get_ad_token():
    curl_cmd = [
    "curl",
    "-X","post",
    f"https://login.microsoftonline.com/{AppConfigs.TENANT_ID}/oauth2/v2.0/token",        
    "-d", "grant_type=client_credentials",        
    "-d", f"client_id={AppConfigs.CLIENT_ID}",        
    "-d", f"client_secret={AppConfigs.CLIENT_SECRET}",        
    "-d", f"scope=api://{AppConfigs.CLIENT_ID}/.default"
    ]
    res=subprocess.run(curl_cmd,capture_output=True,text=True)
    access_token = json.loads(res.stdout)
    return access_token["access_token"]

关键说明

  • 客户端凭证模式(client_credentials)是服务到服务的调用模式,无用户参与,因此只能使用应用权限(对应令牌中的roles声明),不能使用委派权限(对应scope声明)
  • /.default是该模式下的特殊scope,代表客户端被授予的所有应用权限的集合,无法替换为单个自定义scope

内容的提问来源于stack exchange,提问作者Mohammed Sohail

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 15:07:35