Microsoft graph api MS Graph API,应用程序类型,管理员同意,权限“;联系人:ReadWrite“;导致除管理员用户以外的任何用户的访问被拒绝

Microsoft graph api MS Graph API,应用程序类型,管理员同意,权限“;联系人:ReadWrite“;导致除管理员用户以外的任何用户的访问被拒绝,microsoft-graph-api,Microsoft Graph Api,正在尝试从OAuth 2.0 HTTP客户端使用MS Graph API,该客户端根据Azure应用程序注册进行身份验证,以便在同一租户中列出并创建具有O365许可证的任何用户的联系人文件夹和联系人。只有当目标用户是为整个Azure租户授予MS Graph API权限的Azure全局管理员用户时,来自Postman的Graph API调用才会返回有效的JSON结果。尝试访问任何其他租户用户的联系人或联系人文件夹会导致拒绝访问JSON错误响应 根据MS文档,Azure应用程序注册、MS Graph

正在尝试从OAuth 2.0 HTTP客户端使用MS Graph API,该客户端根据Azure应用程序注册进行身份验证,以便在同一租户中列出并创建具有O365许可证的任何用户的联系人文件夹和联系人。只有当目标用户是为整个Azure租户授予MS Graph API权限的Azure全局管理员用户时,来自Postman的Graph API调用才会返回有效的JSON结果。尝试访问任何其他租户用户的联系人或联系人文件夹会导致拒绝访问JSON错误响应

根据MS文档,Azure应用程序注册、MS Graph API、管理员同意、应用程序类型权限联系人。ReadWrite应允许访问所有用户的联系人文件夹和联系人

但是,它只用于获取管理员同意权限的管理员用户的联系人文件夹和联系人。管理员同意的应用程序类型权限的行为类似于非管理员同意的委托类型权限

应用程序注册是否应具有管理员同意的应用程序类型联系人权限,允许访问所有租户用户的联系人,而无需每个最终用户同意访问

这是访问联系人的错误还是预期行为

为什么联系人的读写权限没有“全部”约束

对于未在权限名称上提供“全部”约束元素的权限,应用程序注册是否会忽略应用程序类型Admin Approve,并默认为同意该权限的用户,改为以该用户的身份运行?这是否违背了拥有管理员许可和应用程序类型权限的要点

我们是否需要让每个用户代表联系人文件夹和联系人访问管理员用户

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
offline_access
3) 已授予Microsoft Graph API、委派类型和该Azure应用注册的权限,用于:

https://graph.microsoft.com/Group.ReadWrite.All https://graph.microsoft.com/Directory.Read.All https://graph.microsoft.com/Contacts.ReadWrite
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
以下示例中的数据已[省略]

获取Azure全局管理员用户的联系人(例如:admin_user@fake.com)授予管理员对MS Graph API应用程序类型权限的同意:

请求:

https://graph.microsoft.com/v1.0/users/admin_user@fake.com/contacts
https://graph.microsoft.com/v1.0/users/other_user@fake.com/contacts
https://graph.microsoft.com/v1.0/users/admin_user@fake.com/contactfolders
https://graph.microsoft.com/v1.0/users/other_user@fake.com/contactfolders
答复:

{
    "@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": {}
        }
    ]
}
{
  "error": {
    "code": "ErrorAccessDenied",
    "message": "Access is denied. Check credentials and try again.",
    "innerError": {
      "request-id": "[OMITTED]",
      "date": "2019-11-04T16:40:58"
    }
  }
}
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('admin_user%40fake.com')/contactFolders",
    "value": [
        {
            "id": "[OMITTED]",
            "parentFolderId": "[OMITTED]",
            "displayName": "Test Contacts Folder"
        }
    ]
}
{
  "error": {
    "code": "ErrorAccessDenied",
    "message": "Access is denied. Check credentials and try again.",
    "innerError": {
      "request-id": "[OMITTED]",
      "date": "2019-11-04T16:49:42"
    }
  }
}
尝试获取具有O365许可证的任何其他用户的联系人(例如:其他_user@fake.com):

请求:

https://graph.microsoft.com/v1.0/users/admin_user@fake.com/contacts
https://graph.microsoft.com/v1.0/users/other_user@fake.com/contacts
https://graph.microsoft.com/v1.0/users/admin_user@fake.com/contactfolders
https://graph.microsoft.com/v1.0/users/other_user@fake.com/contactfolders
答复:

{
    "@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": {}
        }
    ]
}
{
  "error": {
    "code": "ErrorAccessDenied",
    "message": "Access is denied. Check credentials and try again.",
    "innerError": {
      "request-id": "[OMITTED]",
      "date": "2019-11-04T16:40:58"
    }
  }
}
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('admin_user%40fake.com')/contactFolders",
    "value": [
        {
            "id": "[OMITTED]",
            "parentFolderId": "[OMITTED]",
            "displayName": "Test Contacts Folder"
        }
    ]
}
{
  "error": {
    "code": "ErrorAccessDenied",
    "message": "Access is denied. Check credentials and try again.",
    "innerError": {
      "request-id": "[OMITTED]",
      "date": "2019-11-04T16:49:42"
    }
  }
}
获取Azure全局管理员用户的联系人文件夹(例如:admin_user@fake.com)授予管理员对MS Graph API应用程序类型权限的同意:

请求:

https://graph.microsoft.com/v1.0/users/admin_user@fake.com/contacts
https://graph.microsoft.com/v1.0/users/other_user@fake.com/contacts
https://graph.microsoft.com/v1.0/users/admin_user@fake.com/contactfolders
https://graph.microsoft.com/v1.0/users/other_user@fake.com/contactfolders
答复:

{
    "@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": {}
        }
    ]
}
{
  "error": {
    "code": "ErrorAccessDenied",
    "message": "Access is denied. Check credentials and try again.",
    "innerError": {
      "request-id": "[OMITTED]",
      "date": "2019-11-04T16:40:58"
    }
  }
}
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('admin_user%40fake.com')/contactFolders",
    "value": [
        {
            "id": "[OMITTED]",
            "parentFolderId": "[OMITTED]",
            "displayName": "Test Contacts Folder"
        }
    ]
}
{
  "error": {
    "code": "ErrorAccessDenied",
    "message": "Access is denied. Check credentials and try again.",
    "innerError": {
      "request-id": "[OMITTED]",
      "date": "2019-11-04T16:49:42"
    }
  }
}
尝试获取具有O365许可证的任何其他用户的联系人文件夹(例如:其他_user@fake.com):

请求:

https://graph.microsoft.com/v1.0/users/admin_user@fake.com/contacts
https://graph.microsoft.com/v1.0/users/other_user@fake.com/contacts
https://graph.microsoft.com/v1.0/users/admin_user@fake.com/contactfolders
https://graph.microsoft.com/v1.0/users/other_user@fake.com/contactfolders
答复:

{
    "@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": {}
        }
    ]
}
{
  "error": {
    "code": "ErrorAccessDenied",
    "message": "Access is denied. Check credentials and try again.",
    "innerError": {
      "request-id": "[OMITTED]",
      "date": "2019-11-04T16:40:58"
    }
  }
}
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('admin_user%40fake.com')/contactFolders",
    "value": [
        {
            "id": "[OMITTED]",
            "parentFolderId": "[OMITTED]",
            "displayName": "Test Contacts Folder"
        }
    ]
}
{
  "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的资源不使用
。所有的
约定。它们依赖于作用域类型(应用程序与委派)来确定应用程序是否可以看到所有用户或仅可以看到经过身份验证的用户的资源

谢谢Marc,这解释了缺少“.All”约束的原因。应用程序注册正在使用管理员同意的应用程序类型权限Contacts.ReadWrite。但它不允许访问任何用户的联系人。它只允许访问授予管理员许可的管理员用户的联系人。还需要什么访问权限?邮递员访问令牌范围:profile openid电子邮件应用程序vs Delegated不是由注册决定的,而是由您用于获取令牌的OAuth授权决定的。为了获取应用程序范围,您需要使用客户端凭据。Postman配置为使用授权类型“授权码”获取访问令牌。你是说它应该设置为授予类型“客户端凭据”,以便获得应用程序范围权限吗?Marc,我知道你将如何授予系统到系统SAN用户访问的“客户端凭据”。我来换一下代币补助,看看效果如何,谢谢。