使用MS Graph应用权限获取其他用户事件遇权限拒绝问题求助
问题描述
使用Microsoft Graph API时,通过**Delegated permissions(委托权限)可正常获取其他用户的日历事件,但使用Application Permission(应用权限)**调用时触发权限拒绝错误:
Microsoft.Graph.ServiceException: 'Code: ErrorAccessDenied
Message: Access is denied.Check credentials and try again.'
报错代码
private string ClientId = "{ClientId}"; private string TenantId = "{TenantId}"; private string SecretKey = "{SecretKey}"; private string[] scopes = new[] { "https://graph.microsoft.com/.default" }; private async void Form1_Load(object? sender, EventArgs e) { await Test2(); } private async Task Test2() { var confidentialClient = ConfidentialClientApplicationBuilder .Create(ClientId) .WithAuthority($"https://login.microsoftonline.com/{TenantId}/oauth2/v2.0/token") .WithClientSecret(SecretKey) .Build(); var authResult = await confidentialClient .AcquireTokenForClient(scopes) .ExecuteAsync(); GraphServiceClient graphClient = new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) => { requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken); }) ); if ((await graphClient.Users.Request() .Filter("UserPrincipalName eq ' tester@tester.com'") .GetAsync()).FirstOrDefault() is User tester) { var calendar1 = await graphClient.Users[tester.Id].Events.Request().GetAsync(); // Raise Error } }
JWT解码后的角色信息
"roles": [ "User.ReadBasic.All", "OnlineMeetings.Read.All", "Calendars.Read", "Mail.ReadBasic.All", "Group.Read.All", "EventListener.Read.All", "Directory.Read.All", "RoleManagement.Read.All", "User.Read.All", "Domain.Read.All", "Schedule.Read.All", "Calendars.ReadBasic.All", "Team.ReadBasic.All", "Mail.Read", "AppRoleAssignment.ReadWrite.All", "Mail.ReadBasic" ],
已尝试的操作
- 增删调整应用权限与委托权限;
- 切换认证方式(密钥↔证书);
- 测试GitHub示例项目代码;
- 校验JWT并在Graph Explorer中测试;
- 配置应用对特定Exchange Online邮箱的权限限制(增删);
- 配置应用对在线会议的访问权限(增删)
排查解决方案
确认应用权限的管理员同意状态
虽然JWT中包含Calendars.Read权限,但应用权限需要全局管理员或Exchange管理员完成同意操作。检查Azure AD应用的权限页面,确认Calendars.Read(或后续替换的Calendars.Read.All)权限旁是否显示“已授予[租户名]管理员同意”,未同意的权限无法生效。替换为正确的应用权限
应用权限下访问其他用户的日历事件,需要的是Calendars.Read.All权限(带.All后缀),而当前JWT中的Calendars.Read仅允许访问应用自身关联的日历。需在Azure AD应用中添加Calendars.Read.All应用权限,重新获取管理员同意后再测试。检查目标用户的日历权限设置
目标用户的日历可能设置了严格的权限,拒绝外部应用访问。可通过Exchange Online PowerShell执行以下命令检查并调整:# 查看目标用户日历权限 Get-MailboxFolderPermission -Identity "tester@tester.com:\Calendar" # 设置默认权限为可查看(Reviewer) Set-MailboxFolderPermission -Identity "tester@tester.com:\Calendar" -User Default -AccessRights Reviewer排查应用访问策略限制
如果应用配置了ApplicationAccessPolicy(特定邮箱访问限制),需确保目标用户在允许列表内:# 查看应用的访问策略 Get-ApplicationAccessPolicy | Where-Object {$_.AppId -eq "{你的ClientId}"} # 添加目标用户到允许列表 New-ApplicationAccessPolicy -AppId "{你的ClientId}" -PolicyScopeGroupId "tester@tester.com" -AccessRight AllowAccess -Description "Allow access to tester's calendar"确认API端点版本
确保使用Microsoft Graph v1.0端点(beta端点可能存在权限兼容性问题),可显式指定端点地址:GraphServiceClient graphClient = new GraphServiceClient("https://graph.microsoft.com/v1.0", new DelegateAuthenticationProvider(...));
内容的提问来源于stack exchange,提问作者이웃집또털어

