microsoft-graph-api - MS Graph API、应用程序类型、管理员同意、权限“Contacts.ReadWrite”导致管理员用户以外的任何用户的访问被拒绝
问题描述
尝试使用针对 Azure 应用注册进行身份验证的 OAuth 2.0 HTTP 客户端中的 MS Graph API 来为同一租户中具有 O365 许可证的任何用户列出和创建联系人文件夹和联系人。仅当目标用户是授予 MS Graph API 权限的整个 Azure 租户的管理员同意的 Azure 全局管理员用户时,来自 Postman 的 Graph API 调用才返回有效的 JSON 结果。尝试访问任何其他租户用户的联系人或联系人文件夹会导致访问被拒绝 JSON 错误响应。
根据 MS 文档,Azure 应用程序注册、MS Graph API、管理员同意、应用程序类型权限 Contacts.ReadWrite 应允许访问所有用户的联系人文件夹和联系人。
但是,它仅适用于获取管理员同意权限的管理员用户的联系人文件夹和联系人。管理员同意的应用程序类型权限的行为类似于非管理员同意的委托类型权限。
应用程序注册是否应获得管理员同意,应用程序类型联系人权限允许访问所有租户用户的联系人,而无需每个最终用户同意访问?
这是访问联系人的错误或预期行为吗?
为什么联系人读写权限没有“全部”约束?
对于未在权限名称上提供“全部”约束元素的权限,应用程序注册是否会忽略应用程序类型管理员同意并默认为同意该权限的用户,而是以该用户身份运行?这不违背拥有管理员同意和应用程序类型权限的观点吗?
我们是否需要让每个用户将联系人文件夹和联系人访问权限委托给管理员用户?
1) 创建了 Azure 应用注册 2) 授予 Microsoft Graph API、应用程序类型、对该 Azure 应用注册的权限:
https://graph.microsoft.com/Group.ReadWrite.All https://graph.microsoft.com/Directory.Read.All https://graph.microsoft.com/Contacts.ReadWrite
3) 授予 Microsoft Graph API、委托类型、对该 Azure 应用注册的权限:
offline_access
4) 使用范围配置 Postman OAuth 2.0 访问令牌:
offline_access https://graph.microsoft.com/Group.ReadWrite.All https://graph.microsoft.com/Directory.Read.All https://graph.microsoft.com/Contacts.ReadWrite
以下示例中的数据已[省略]。
获取授予 MS Graph API 应用程序类型权限管理员同意的 Azure 全局管理员用户(例如:admin_user@fake.com)的联系人:
要求:
https://graph.microsoft.com/v1.0/users/admin_user@fake.com/contacts
回复:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('admin_user%40fake.com')/contacts",
"value": [
{
"@odata.etag": "W/\"[OMITTED]\"",
"id": "[OMITTED]",
"createdDateTime": "2019-10-25T17:11:06Z",
"lastModifiedDateTime": "2019-10-30T13:11:13Z",
"changeKey": "[OMITTED]",
"categories": [],
"parentFolderId": "[OMITTED]",
"birthday": null,
"fileAs": "test, Test",
"displayName": "Test test",
"givenName": "Test",
"initials": null,
"middleName": null,
"nickName": null,
"surname": "test",
"title": null,
"yomiGivenName": null,
"yomiSurname": null,
"yomiCompanyName": null,
"generation": null,
"imAddresses": [],
"jobTitle": null,
"companyName": null,
"department": null,
"officeLocation": null,
"profession": null,
"businessHomePage": null,
"assistantName": null,
"manager": null,
"homePhones": [
"666-666-6666"
],
"mobilePhone": "555-555-5555",
"businessPhones": [
"777-777-7777"
],
"spouseName": null,
"personalNotes": "Test",
"children": [],
"emailAddresses": [],
"homeAddress": {},
"businessAddress": {},
"otherAddress": {}
}
]
}
尝试获取具有 O365 许可证的任何其他用户的联系人(例如:other_user@fake.com):
要求:
https://graph.microsoft.com/v1.0/users/other_user@fake.com/contacts
回复:
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again.",
"innerError": {
"request-id": "[OMITTED]",
"date": "2019-11-04T16:40:58"
}
}
}
获取授予 MS Graph API 应用程序类型权限管理员同意的 Azure 全局管理员用户(例如:admin_user@fake.com)的联系人文件夹:
要求:
https://graph.microsoft.com/v1.0/users/admin_user@fake.com/contactfolders
回复:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('admin_user%40fake.com')/contactFolders",
"value": [
{
"id": "[OMITTED]",
"parentFolderId": "[OMITTED]",
"displayName": "Test Contacts Folder"
}
]
}
尝试使用 O365 许可证获取任何其他用户的联系人文件夹(例如:other_user@fake.com):
要求:
https://graph.microsoft.com/v1.0/users/other_user@fake.com/contactfolders
回复:
{
"error": {
"code": "ErrorAccessDenied",
"message": "Access is denied. Check credentials and try again.",
"innerError": {
"request-id": "[OMITTED]",
"date": "2019-11-04T16:49:42"
}
}
}
解决方案
从文档中:
应用可以在其他用户的联系人文件夹中获取联系人的情况有两种:
换句话说,当使用委托范围时,用户只能访问他们自己的联系人或明确与他们共享的联系人。
如果你想访问任何用户的联系人,你需要使用Contacts.Read
或Contacts.ReadWrite
应用范围。
通常,基于 Exchange 的资源不使用这些.All
约定。它们依赖于范围类型(Application vs Delegated)来确定应用程序是可以看到所有用户还是只能看到经过身份验证的用户的资源。
推荐阅读
- c# - .NET Core 3.1 中奇怪的 SQL Server 连接问题
- java - 用 JAVA 加密的 AES 密钥快速解密
- mysql - 按标准排序 - 使用递归 CTE
- r - R:按组替换各种值
- typescript - 预期 1 个参数,但得到 0
- .net - 在 Azure DevOps 持续部署期间无法获取资源类型“Microsoft.Web/Sites”和资源名称“AppService”的资源 ID
- node.js - 由于缺少节点模块,无法在本地机器上运行 React 应用程序
- c# - 我需要使用 Linq 在通用列表中找到整数总和的最大总数
- c++ - 在这个宏定义的消息传递、日志记录、错误处理系统中是否有任何不可预见的副作用?
- javascript - 在数组上循环 getClientOriginalName()