首页 > 解决方案 > 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"
    }
  }
}

应用程序注册的当前许可

标签: microsoft-graph-api

解决方案


从文档中:

应用可以在其他用户的联系人文件夹中获取联系人的情况有两种:

  • 如果应用程序具有应用程序权限,或者,
  • 如果应用程序具有来自一个用户的适当委派权限,并且另一个用户已与该用户共享联系人文件夹,或者已向该用户授予委派访问权限。查看详细信息和示例

换句话说,当使用委托范围时,用户只能访问他们自己的联系人或明确与他们共享的联系人。

如果你想访问任何用户的联系人,你需要使用Contacts.ReadContacts.ReadWrite 应用范围。

通常,基于 Exchange 的资源不使用这些.All约定。它们依赖于范围类型(​​Application vs Delegated)来确定应用程序是可以看到所有用户还是只能看到经过身份验证的用户的资源。


推荐阅读