使用Arduino通过MS Graph API获取Azure AD用户日历事件遇403权限问题
解决Arduino调用MS Graph获取其他用户日历事件的403权限问题
问题背景
通过Arduino代码使用MS Graph API获取Azure AD中其他用户的日历事件时,返回HTTP 403错误,错误响应如下:
{ "error": { "code": "ErrorAccessDenied", "message": "Access is denied. Check credentials and try again." } }
但使用Graph Explorer可正常获取数据。已完成AAD应用注册,添加了委派+应用权限并授予管理员同意,采用设备登录流程,令牌解码确认包含Calendars.Read等权限范围,且获取Presence数据正常。
核心排查与解决方案
1. 明确权限类型与访问场景的匹配
你当前使用的设备码流程属于委派权限,代表的是登录用户的身份,而非应用本身的身份:
- 委派权限
Calendars.Read默认仅允许访问登录用户自己的日历,无法直接访问其他用户的日历(除非目标用户主动将日历共享给登录用户) - 若要无需用户共享即可访问任意用户的日历,需要使用应用权限的
Calendars.Read,但应用权限必须搭配客户端凭证流程(而非设备码流程),因为应用权限不需要用户交互登录
2. 检查登录用户的实际权限
Graph Explorer能正常获取数据,大概率是因为你在Graph Explorer中使用的账号本身拥有访问目标用户日历的权限(比如你是租户管理员,或目标用户已将日历共享给你),但Arduino设备码流程中登录的用户并不具备该权限:
- 确认Arduino登录的用户是否被目标用户授予了日历访问权限(可在Outlook中检查目标用户的日历共享设置)
- 若无法依赖用户共享,需切换到应用权限方案
3. 调整权限配置与认证流程
方案一:继续使用设备码流程(委派身份)
- 将应用的委派权限替换为
Calendars.Read.Shared,并重新获取管理员同意 - 确保目标用户已将日历共享给Arduino登录的用户
- 重新启动设备码流程获取新令牌,再尝试调用接口
方案二:切换为应用权限(无用户交互)
- 在AAD应用注册中,删除原有的委派权限,添加应用权限类型的
Calendars.Read,并获取管理员同意 - 修改Arduino代码,弃用设备码流程,改用客户端凭证流程(通过客户端ID+客户端密钥/证书获取访问令牌)
- 调用接口时,无需指定用户登录身份,直接以应用身份访问目标用户日历
4. 验证令牌的关键字段
再次解码令牌,确认以下字段:
aud:必须为https://graph.microsoft.com,确保令牌针对Graph API颁发roles(应用权限时):需包含Calendars.Read角色scp(委派权限时):需包含Calendars.Read.Shared(若用方案一)
5. 确认目标用户信息正确性
检查调用接口中的<user>@<tenant>.nl是否为目标用户的正确UPN,确认该用户存在于你的Azure AD租户中,且未被禁用。
内容的提问来源于stack exchange,提问作者charmesal
相关产品推荐
相关产品推荐

