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

使用Microsoft Graph API获取Outlook日历事件时遇权限拒绝错误

解决Microsoft Graph API客户端凭证流访问日历时的ErrorAccessDenied错误

问题场景

使用客户端凭证流调用Microsoft Graph API的日历相关端点(Get Calendars、List Events、Get Schedule等)时,返回权限拒绝错误:

{'error': {'code': 'ErrorAccessDenied', 'message': 'Access is denied. Check credentials and try again.'}}

已完成以下配置:

  • Azure AD应用注册,权限类型为Application
  • 已授予Calendars.Read、Calendars.ReadWrite、User.ReadAll权限并完成管理员同意
  • 可成功生成Access Token,且能通过该Token读取用户信息,仅日历相关请求失败

排查与解决步骤

1. 确认目标用户日历的文件夹权限

客户端凭证流的应用权限依赖Exchange Online的日历文件夹权限设置。即使应用有Calendars.Read权限,若目标用户的日历未对组织开放读取权限,应用仍无法访问:

  • 登录Exchange Admin Center,找到目标用户邮箱,进入权限 -> 日历权限,确认默认用户的权限为审阅者或更高级别。
  • 或用PowerShell命令检查:
Get-MailboxFolderPermission -Identity "<用户邮箱>:\Calendar"

2. 验证Access Token的权限范围

解码Access Token(使用本地JWT解码工具),检查roles字段是否包含Calendars.Read/Calendars.ReadWrite:

  • 若缺失这些权限,需确认:
    • 管理员同意操作已完成(在Azure AD门户的企业应用权限页面确认状态为"已授予")
    • 获取Token时使用的范围为https://graph.microsoft.com/.default(客户端凭证流必须使用该范围)

3. 检查目标用户的许可证状态

确认目标用户拥有Exchange Online(或包含日历功能的O365订阅)有效许可证,无许可证用户的日历无法通过Graph API访问。

4. 排查Exchange Online应用访问策略

部分租户会配置应用访问策略限制第三方应用访问邮箱数据:

  • 登录Exchange Admin Center,进入权限 -> 应用访问策略,检查是否存在阻止该应用的规则。

5. 确认API请求端点格式

客户端凭证流无用户上下文,不能使用/me路径,必须指定具体用户ID(邮箱或对象ID):
正确端点示例:

GET https://graph.microsoft.com/v1.0/users/{user-id}/calendars
GET https://graph.microsoft.com/v1.0/users/{user-id}/events

6. 检查Azure AD应用的权限状态

在Azure AD门户企业应用 -> 目标应用 -> 权限页面,确认Calendars.Read/Calendars.ReadWrite的权限状态为"已授予",而非"待同意"。

示例代码检查点

确保MSAL获取Token及API调用代码符合客户端凭证流要求:

from msal import ConfidentialClientApplication
import requests

client_id = "YOUR_CLIENT_ID"
client_secret = "YOUR_CLIENT_SECRET"
tenant_id = "YOUR_TENANT_ID"
target_user_id = "TARGET_USER_EMAIL_OR_OBJECT_ID"

# 初始化MSAL客户端
app = ConfidentialClientApplication(
    client_id,
    authority=f"https://login.microsoftonline.com/{tenant_id}",
    client_credential=client_secret
)

# 获取客户端凭证流Token(必须使用.default范围)
result = app.acquire_token_for_client(scopes=["https://graph.microsoft.com/.default"])

if "access_token" in result:
    # 调用日历API时指定目标用户ID
    response = requests.get(
        f"https://graph.microsoft.com/v1.0/users/{target_user_id}/calendars",
        headers={"Authorization": f"Bearer {result['access_token']}"}
    )
    print(response.json())

内容的提问来源于stack exchange,提问作者Rathish Kumar B

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 20:45:39