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

MSAL成功获取Bearer令牌,但调用Microsoft Graph提示权限不足

问题:使用Microsoft Graph访问邮箱时出现权限不足错误

背景

  • 原通过exchangelib库以Basic Auth方式访问组织邮箱,因微软不再支持Basic Auth,改用Microsoft Graph开发Python应用,需求为读取并转发指定邮箱someuser@myorganization.com的邮件。
  • 组织已在Microsoft身份平台注册名为“Email Service App”的应用,提供的权限截图显示已授予相关权限(本人无Graph控制台访问权限)。
    Service Email App API Permissions

代码实现(参考MSAL示例)

初始化配置与应用实例

config_data = {
    "authority": "https://login.microsoftonline.com/<secret value>",
    "client_id": "<secret value>",
    "scope": ["https://graph.microsoft.com/.default"],
    "secret": "<secret value>",
    "endpoint": "https://graph.microsoft.com/v1.0/users"
}
# Optional logging
logging.basicConfig(level=logging.DEBUG)  # Enable DEBUG log for entire script
logging.getLogger("msal").setLevel(logging.INFO)  # Optionally disable MSAL DEBUG logs

config = json.loads(config_data)

# Create a preferably long-lived app instance which maintains a token cache.
app = msal.ConfidentialClientApplication(
    config["client_id"], authority=config["authority"],
    client_credential=config["secret"],
)

初始化阶段日志输出

DEBUG:urllib3.util.retry:Converted retries value: 1 -> Retry(total=1, connect=None, read=None, redirect=None, status=None)
DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): login.microsoftonline.com:443
DEBUG:urllib3.connectionpool:https://login.microsoftonline.com:443 "GET /<secret>/v2.0/.well-known/openid-configuration HTTP/1.1" 200 1753

尝试从缓存获取令牌

# The pattern to acquire a token looks like this.
result = None

# Firstly, looks up a token from cache
# Since we are looking for token for the current app, NOT for an end user,
# notice we give account parameter as None.
result = app.acquire_token_silent(config["scope"], account=None)

缓存查询阶段日志输出

INFO:root:No suitable token exists in cache. Let's get a new one from AAD.
DEBUG:urllib3.connectionpool:https://login.microsoftonline.com:443 "POST /<secret>/oauth2/v2.0/token HTTP/1.1" 200 1589

获取新令牌

if not result:
    logging.info("No suitable token exists in cache. Let's get a new one from AAD.")
    result = app.acquire_token_for_client(scopes=config["scope"])

获取新令牌阶段日志输出

INFO:root:No suitable token exists in cache. Let's get a new one from AAD.
DEBUG:urllib3.connectionpool:https://login.microsoftonline.com:443 "POST /<secret>/oauth2/v2.0/token HTTP/1.1" 200 1589

令牌输出(已成功获取)

{'token_type': 'Bearer',
 'expires_in': 3599,
 'ext_expires_in': 3599,
 'access_token': <removed, was successful>}

调用Microsoft Graph API

if "access_token" in result:
    # Calling graph using the access token
    graph_data = requests.get(  # Use token to call downstream service
        config["endpoint"],
        headers={'Authorization': 'Bearer ' + result['access_token']},).json()
    print("Graph API call result: %s" % json.dumps(graph_data, indent=2))

else:
    print(result.get("error"))
    print(result.get("error_description"))
    print(result.get("correlation_id"))  # You may need this when reporting a bug

API调用阶段日志输出

DEBUG:urllib3.connectionpool:Starting new HTTPS connection (1): graph.microsoft.com:443
DEBUG:urllib3.connectionpool:https://graph.microsoft.com:443 "GET /v1.0/users HTTP/1.1" 403 None

Graph API call result: {
  "error": {
    "code": "Authorization_RequestDenied",
    "message": "Insufficient privileges to complete the operation.",
    "innerError": {
      "date": "2022-11-06T13:07:13",
      "request-id": "13a2593f-e9c9-4844-aca5-7c362a7f83b8",
      "client-request-id": "13a2593f-e9c9-4844-aca5-7c362a7f83b8"
    }
  }
}

疑问

已成功获取Bearer令牌,但调用Graph API时返回权限不足错误,而权限截图显示已授予相关权限。请问问题出在代码实现、组织的Microsoft Graph配置,还是其他原因?

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 16:10:34