使用扩展将自定义数据添加到资源

Microsoft Graph 提供单个 API 终结点,以通过 用户消息 等资源访问以人为本的丰富数据和见解。 还可以通过将自定义属性添加到资源实例来扩展 Microsoft Graph,而无需使用外部数据存储。

本文介绍 Microsoft Graph 如何支持扩展其资源、可用于添加自定义属性的选项以及何时使用这些属性。

重要

请勿使用扩展来存储敏感的个人身份信息,例如帐户凭据、政府标识号、持卡人数据、财务帐户数据、医疗保健信息或敏感背景信息。

本文中提到的扩展与以下功能不相似:

为什么要将自定义数据添加到 Microsoft Graph?

  • 作为 ISV 开发人员,你可能会决定通过扩展 用户 资源,让应用处于轻量级水平,并将特定于应用的用户配置文件数据存储在 Microsoft Graph 中。
  • 或者,你可能希望保留应用的现有用户配置文件存储区,并将特定于应用的标识符添加到 用户 资源。
  • 作为企业开发人员,你生成的内部应用程序可能依赖于组织的 HR 特定数据。 通过将此自定义数据存储在 Microsoft Graph 中,可以简化多个应用程序中的集成。

Microsoft Graph 中的自定义数据选项

Microsoft Graph 提供了四种类型的扩展来添加自定义数据。

  • 扩展属性
  • 目录 (Microsoft Entra ID) 扩展
  • 架构扩展
  • 开放扩展

扩展属性

Microsoft Entra ID提供一组 15 个扩展属性,其中包含用户和设备资源上的预定义名称。 这些属性最初是在本地 Active Directory (AD) 和 Microsoft Exchange 中提供的自定义属性。 但是,现在可以使用它们来同步本地 AD 和 Microsoft Exchange 数据,以便通过 Microsoft Graph Microsoft Entra ID。

有关 Microsoft Exchange 中的这些属性的详细信息,请参阅 Exchange Server 中的自定义属性

开发者体验

可以通过 onPremisesExtensionAttributesextensionAttributes 属性,使用 15 个扩展属性将字符串值存储在用户设备资源实例上。 可以在创建新资源实例或更新现有资源实例时分配值。 还可以按值进行筛选。

在扩展属性中添加或更新数据

以下示例演示如何使用 PATCH 方法通过更新作将数据存储在 extensionAttribute1 中,并从 extensionAttribute13 中删除现有数据。

PATCH https://graph.microsoft.com/v1.0/users/071cc716-8147-4397-a5ba-b2105951cc0b

{
    "onPremisesExtensionAttributes": {
        "extensionAttribute1": "skypeId.adeleVance",
        "extensionAttribute13": null
    }
}

请求会返回 204 No Content 响应对象。

读取扩展属性

请求
GET https://graph.microsoft.com/v1.0/users?$select=id,displayName,onPremisesExtensionAttributes
响应
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(id,displayName,onPremisesExtensionAttributes)",
    "value": [
        {
            "id": "071cc716-8147-4397-a5ba-b2105951cc0b",
            "displayName": "Adele Vance",
            "onPremisesExtensionAttributes": {
                "extensionAttribute1": "Contractor",
                "extensionAttribute2": "50",
                "extensionAttribute3": null,
                "extensionAttribute4": "1478354",
                "extensionAttribute5": "10239390",
                "extensionAttribute6": null,
                "extensionAttribute7": null,
                "extensionAttribute8": null,
                "extensionAttribute9": null,
                "extensionAttribute10": "11",
                "extensionAttribute11": null,
                "extensionAttribute12": "/o=ExchangeLabs/ou=Exchange Administrative Group (FYDIBOHF47SPDLT)/cn=Recipients/cn=5ee781fc7egc7aa0b9394bddb44e7f04-Adele Vance",
                "extensionAttribute13": null,
                "extensionAttribute14": null,
                "extensionAttribute15": null
            }
        }
    ]
}

使用扩展属性属性的注意事项

只能为未从本地 AD 同步的对象更新 onPremisesExtensionAttributes 对象。

Microsoft Graph 已定义 15 个扩展属性,无法更改其属性名称。 因此,不能将自定义名称(如 SkypeId )用于扩展属性。 组织必须跟踪正在使用的扩展属性属性,以避免无意中覆盖其数据。

目录 (Microsoft Entra ID) 扩展

目录扩展 为开发人员提供了目录对象的强类型化、可发现和可筛选的扩展体验。

通过 创建 extensionProperty 作在应用程序上注册目录扩展。 必须显式面向特定和受支持的目录对象。 用户或管理员同意租户中的应用程序后,可以在租户中立即访问扩展属性。 租户中的所有授权应用程序都可以读取和写入目标目录对象实例上定义的任何扩展属性上的数据。

有关可指定为目录扩展的目标对象的资源类型的列表,请参阅 扩展类型的比较

开发者体验

可以通过 extensionProperty 资源及其关联方法管理目录扩展定义。 用于管理资源实例的 REST API 请求处理数据。

定义目录扩展

必须先定义目录扩展,然后才能将目录扩展添加到资源实例。

请求

在以下请求中, 30a5435a-1871-485c-8c7b-65f69e287e7b 是拥有目录扩展的应用程序的对象 ID。 可以创建存储值集合的目录扩展。

POST https://graph.microsoft.com/v1.0/applications/30a5435a-1871-485c-8c7b-65f69e287e7b/extensionProperties

{
    "name": "jobGroupTracker",
    "dataType": "String",
    "targetObjects": [
        "User"
    ]
}
响应

使用遵循以下命名约定的扩展名称创建名为 extension_b7d8e648520f41d3b9c0fdeb91768a0a_jobGroupTracker 的目录扩展属性: extension_{appId-without-hyphens}_{extensionProperty-name}

HTTP/1.1 201 Created
Content-type: application/json

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#applications('30a5435a-1871-485c-8c7b-65f69e287e7b')/extensionProperties/$entity",
    "id": "4e3dbc8f-ca32-41b4-825a-346215d7d20f",
    "deletedDateTime": null,
    "appDisplayName": "HR-sync-app",
    "dataType": "String",
    "isMultiValued": false,
    "isSyncedFromOnPremises": false,
    "name": "extension_b7d8e648520f41d3b9c0fdeb91768a0a_jobGroupTracker",
    "targetObjects": [
        "User"
    ]
}

将目录扩展属性添加到目标对象

定义目录扩展后,将其添加到目标对象类型的实例。 在创建目标对象的新实例或更新现有对象时,可以将数据存储在目录扩展中。 以下示例演示如何在创建新 用户 对象时将数据存储在目录扩展中。

POST https://graph.microsoft.com/v1.0/users

{
    "accountEnabled": true,
    "displayName": "Adele Vance",
    "mailNickname": "AdeleV",
    "userPrincipalName": "AdeleV@contoso.com",
    "passwordProfile": {
        "forceChangePasswordNextSignIn": false,
        "password": "xWwvJ]6NMw+bWH-d"
    },
    "extension_b7d8e648520f41d3b9c0fdeb91768a0a_jobGroupTracker": "JobGroupN"
}

请求会在响应正文中返回 201 Created 响应代码和 用户对象。

检索目录扩展

以下示例演示如何在资源实例上显示目录扩展和关联数据。 默认情况下,扩展属性通过 beta 终结点返回,但仅 $select 通过 v1.0 终结点返回 。

请求

GET https://graph.microsoft.com/beta/users?$select=id,displayName,extension_b7d8e648520f41d3b9c0fdeb91768a0a_jobGroupTracker,extension_b7d8e648520f41d3b9c0fdeb91768a0a_permanent_pensionable

响应

HTTP/1.1 200 OK
Content-type: application/json

{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users(id,displayName,extension_b7d8e648520f41d3b9c0fdeb91768a0a_jobGroupTracker,extension_b7d8e648520f41d3b9c0fdeb91768a0a_permanent_pensionable)",
    "value": [
        {
            "id": "63384f56-42d2-4aa7-b1d6-b10c78f143a2",
            "displayName": "Adele Vance",
            "extension_b7d8e648520f41d3b9c0fdeb91768a0a_jobGroupTracker": "E4",
            "extension_b7d8e648520f41d3b9c0fdeb91768a0a_permanent_pensionable": true
        }
    ]
}

更新或删除目录扩展

若要更新或删除资源实例的目录扩展的值,请使用 PATCH 方法。 若要删除扩展属性及其关联的值,请将其值设置为 null

以下请求更新一个目录扩展的值,并删除另一个扩展属性。

PATCH https://graph.microsoft.com/v1.0/users/63384f56-42d2-4aa7-b1d6-b10c78f143a2

{
    "extension_b7d8e648520f41d3b9c0fdeb91768a0a_permanent_pensionable": null,
    "extension_b7d8e648520f41d3b9c0fdeb91768a0a_jobGroupTracker": "E4"
}

请求会返回 204 No Content 响应代码。

使用目录扩展的注意事项

如果意外删除了目录扩展定义,则存储在关联属性中的任何数据都将无法发现。 若要恢复数据,请在同一所有者应用上创建一个新的目录扩展定义,其名称与已删除的定义相同。

在将相应的扩展属性更新为 null之前删除定义对象时,该属性将计入对象的 100 限制。

在删除关联的扩展属性中的数据之前删除定义时,无法通过 Microsoft Graph 知道扩展属性是否存在,即使不可发现属性计数超过 100 限制也是如此。

删除主租户中的所有者应用会使关联的目录扩展及其数据无法被发现。 还原所有者应用时,它会还原目录扩展定义, 但不会 立即发现目录扩展属性或其数据;因为还原应用不会自动还原租户中的关联服务主体。 若要使目录扩展属性及其数据可被发现,请创建新的服务主体或还原已删除的服务主体。 不会对已同意应用的其他租户进行更改。

架构扩展

Microsoft Graph 架构扩展 在概念上类似于目录扩展。 首先,定义架构扩展。 然后,使用它扩展具有强类型自定义属性的支持资源实例。 此外,还可以控制架构扩展的状态,让它可被其他应用发现。

有关支持架构扩展的资源类型列表,请参阅 扩展类型的比较

开发者体验

创建架构扩展定义时,必须为其 ID 提供唯一名称。你有两个命名选项:

  • 如果已有通过租户验证的虚 .com.net.gov.edu.org 域,请使用域名和架构名称来定义唯一名称,格式为 {domainName}_{schemaName}。 例如,如果虚域为 contoso.com,则可以定义 contoso_mySchemaID。 强烈建议使用此选项。
  • 或者,将 ID 设置为架构名称, (不带域名前缀) 。 例如,mySchema。 Microsoft Graph 根据提供的名称为你分配字符串 ID,格式如下: ext{8-random-alphanumeric-chars}_{schema-name}。 例如,extkvbmkofy_mySchema

ID 是用于在扩展资源实例上存储数据的复杂类型的名称。

注册架构扩展后,与关联的所有者应用程序同一租户中的所有应用程序都可以在处于 状态 InDevelopment 时使用该扩展。 处于 状态 Available 时,任何租户中的所有应用程序都可以使用它。 与目录扩展一样,授权的应用可以在目标对象上定义的任何扩展上读取和写入数据。

使用单独的 API作集来管理相应架构扩展属性中的架构扩展 定义 和数据。 要管理扩展资源实例上的架构扩展数据,请使用你用于管理资源实例的同一 REST 请求。

  • 创建新用户时,使用 POST 将数据存储在架构扩展属性中。
  • 使用 PATCH 将数据存储在架构扩展属性中,或者更新或删除存储的数据。
    • 若要从属性中删除数据,请将其值设置为 null
    • 若要从 所有 属性中删除数据,请将每个属性设置为 null。 如果所有属性均为 null,则也会删除架构扩展对象。
    • 若要更新任何属性,请在请求正文中仅指定已更改的属性。 省略的属性不会更新,并保留其以前的值。
  • 使用 GET 读取租户中所有用户或单个用户的架构扩展属性。

定义架构扩展

请求
POST https://graph.microsoft.com/v1.0/schemaExtensions

{
    "id": "graphLearnCourses",
    "description": "Graph Learn training courses extensions",
    "targetTypes": [
        "user"
    ],
    "properties": [
        {
            "name": "courseId",
            "type": "Integer"
        },
        {
            "name": "courseName",
            "type": "String"
        },
        {
            "name": "courseType",
            "type": "String"
        }
    ]
}
响应
{
    "@odata.context": "https://graph.microsoft.com/beta/$metadata#schemaExtensions/$entity",
    "id": "extkmpdyld2_graphLearnCourses",
    "description": "Graph Learn training courses extensions",
    "targetTypes": [
        "user"
    ],
    "status": "InDevelopment",
    "properties": [
        {
            "name": "courseId",
            "type": "Integer"
        },
        {
            "name": "courseName",
            "type": "String"
        },
        {
            "name": "courseType",
            "type": "String"
        }
    ]
}

将架构扩展添加到资源实例

定义架构扩展后,可以将扩展属性添加到目标对象类型的实例。 在创建目标对象的新实例或更新现有对象时,可以将数据存储在架构扩展中。 下面的示例演示如何在创建新的用户对象时将数据存储在架构扩展属性中。

POST https://graph.microsoft.com/beta/users

{
    "accountEnabled": true,
    "displayName": "Adele Vance",
    "mailNickname": "AdeleV",
    "userPrincipalName": "AdeleV@contoso.com",
    "passwordProfile": {
        "forceChangePasswordNextSignIn": false,
        "password": "xWwvJ]6NMw+bWH-d"
    },
    "extkmpdyld2_graphLearnCourses": {
        "courseId": 100,
        "courseName": "Explore Microsoft Graph",
        "courseType": "Online"
    }
}

请求在 201 Created 响应正文中返回响应代码和 schemaExtension 对象。

更新或删除架构扩展属性

使用 PATCH作更新架构扩展或删除现有架构扩展。 要从资源实例中删除扩展属性及其关联值,请将其值设置为 null

以下示例删除 courseId 属性的值并更新 courseType 属性。 要完整删除 extkmpdyld2_graphLearnCourses 扩展属性,请将其值设置为 null

PATCH https://graph.microsoft.com/beta/users/0668e673-908b-44ea-861d-0661297e1a3e

{
    "extkmpdyld2_graphLearnCourses": {
        "courseType": "Instructor-led",
        "courseId": null
    }
}

请求会返回 204 No Content 响应对象。

检索架构扩展属性

要读取资源实例上的架构扩展属性,请在 $select 请求中指定扩展名。

请求
GET https://graph.microsoft.com/beta/users/0668e673-908b-44ea-861d-0661297e1a3e?$select=id,displayName,extkmpdyld2_graphLearnCourses
响应
HTTP/1.1 200 OK
Content-type: application/json

{
    "@odata.context": "https://graph.microsoft.com/beta/$metadata#users(id,displayName,extkmpdyld2_graphLearnCourses)/$entity",
    "id": "63384f56-42d2-4aa7-b1d6-b10c78f143a2",
    "displayName": "Adele Vance",
    "extkmpdyld2_graphLearnCourses": {
        "@odata.type": "#microsoft.graph.ComplexExtensionValue",
        "courseType": "Instructor-led",
        "courseName": "Explore Microsoft Graph",
        "courseId": null
    }
}

使用架构扩展的注意事项

架构扩展必须具有所有者应用。 无法将架构扩展的所有权重新分配给其他应用。

如果删除架构扩展定义而不将架构扩展设置为 null,则会使属性及其关联的用户数据不可发现。

如果删除主租户中的所有者应用,则不会删除关联的架构扩展定义或属性及其存储的数据。 你仍然可以读取、删除或更新用户的架构扩展属性。 但是,无法更新架构扩展定义。

开放扩展

Microsoft Graph 开放扩展开放类型 ,可提供一种简单灵活的方式将非类型化数据直接添加到资源实例。 这些扩展不是强类型化、可发现或可筛选的。

有关支持 Microsoft Graph 开放扩展的资源类型列表,请参阅 扩展类型的比较

开发者体验

可以通过资源实例的扩展导航属性访问开放 扩展 及其数据。 使用开放扩展,可以对相关属性进行分组,以便于访问和管理。

定义和管理资源实例上的开放扩展。 每个打开的扩展都对其对象是唯一的,因此无需在所有对象上应用一致的模式。 例如,在同一租户中:

  • Adele 的用户对象可以具有名为 socialSettings 的 开放扩展,该扩展具有三个属性: linkedInProfileskypeIdxboxGamertag
  • Allan 的用户对象不能有 open extension 属性。
  • Alex 的用户对象可以具有名为 socialSettings 的 开放扩展,该扩展具有五个属性: 主题颜色语言字体fontSize

打开扩展属性可以具有任何有效的 JSON 结构。

创建开放扩展

以下示例演示具有三个属性的开放扩展定义,以及自定义属性和关联数据在资源实例上的显示方式。

POST https://graph.microsoft.com/v1.0/users/3fbd929d-8c56-4462-851e-0eb9a7b3a2a5/extensions

{
    "@odata.type": "#microsoft.graph.openTypeExtension",
    "extensionName": "com.contoso.socialSettings",
    "skypeId": "skypeId.AdeleV",
    "linkedInProfile": "www.linkedin.com/in/testlinkedinprofile",
    "xboxGamerTag": "AwesomeAdele",
    "id": "com.contoso.socialSettings"
}

请求会在响应正文中返回 201 Created 响应代码和 openTypeExtension 对象。

更新现有开放扩展

要更新开放扩展,必须在请求正文中指定其所有属性。 否则,将从打开的扩展中删除未指定的属性。 可以将 属性显式设置为 以 null 将其保留在打开的扩展中。

以下请求仅指定 linkedInProfilexboxGamerTag 属性。 当 linkedInProfile 属性保持不变时,将更新 xboxGamerTag 属性的值。 此请求还会删除未指定的 skypeId 属性。

PATCH https://graph.microsoft.com/v1.0/users/3fbd929d-8c56-4462-851e-0eb9a7b3a2a5/extensions/com.contoso.socialSettings

{
    "xboxGamerTag": "FierceAdele",
    "linkedInProfile": "www.linkedin.com/in/testlinkedinprofile"
}

此请求会返回 204 No Content 响应代码。

检索开放扩展

GET https://graph.microsoft.com/v1.0/users/3fbd929d-8c56-4462-851e-0eb9a7b3a2a5/extensions/com.contoso.socialSettings

{
    "@odata.context": "https://graph.microsoft.com/beta/$metadata#users('3fbd929d-8c56-4462-851e-0eb9a7b3a2a5')/extensions/$entity",
    "@odata.type": "#microsoft.graph.openTypeExtension",
    "xboxGamerTag": "FierceAdele",
    "linkedInProfile": "www.linkedin.com/in/testlinkedinprofile",
    "id": "com.contoso.socialSettings"
}

使用开放扩展的注意事项

删除创建者应用不会影响打开的扩展或其存储的数据。

扩展类型的比较

下表比较了扩展类型。 使用此比较来确定哪个选项最适合你的方案。

功能 扩展属性 1-15 目录扩展 架构扩展 开放扩展
支持的资源类型 user
设备
user
group
administrativeUnit
application
设备
组织
用户
group
administrativeUnit
联系人
设备
事件(用户和组日历)
邮件
组织
帖子
user

联系人
设备
事件1(用户和组日历)
邮件
组织
帖子
todoTask
todoTaskList
强类型
Filterable
可以存储集合
绑定到“所有者”应用程序
界定访问权限 将值分配给目标对象实例的预定义属性 在应用程序级别定义,然后分配给目标对象实例 为租户定义,然后分配给目标对象实例 在对象实例上定义和分配
可发现性 选择或筛选目标对象实例 列出、选择或筛选应用程序级别的 GET 定义;选择或筛选 GET 分配的目标对象 列出或筛选 GET 租户范围的定义;选择或筛选 GET 分配的目标对象 列出或选择 GET 定义和分配的目标对象
管理方式 Microsoft Graph
Exchange 管理中心
Microsoft Graph Microsoft Graph Microsoft Graph
使用 AD Connect 将数据从本地同步到扩展 是,对于用户
使用自定义扩展属性和数据创建 动态成员资格规则
可用于自定义令牌声明 是 (12)
在 Azure AD B2C 中提供
在 Microsoft Entra 外部 ID 中可用
限制
  • 每个用户或设备资源实例 15 个预定义属性
  • 每个资源实例 100 个扩展值
  • 每个所有者应用最多五个定义
  • 每个资源实例 100 个扩展值(仅限目录对象)
  • 每个资源实例每个创建者应用两个开放扩展2
  • 最大 每个打开的扩展 2 Kb2
  • 对于 Outlook 资源,每个开放扩展都存储在 MAPI 命名属性3
  • 注意

    1 由于现有的服务限制,代理人无法在共享邮箱日历中创建打开的附加扩展的事件。 尝试这样做会导致 ErrorAccessDenied 响应。

    2 开放扩展的这些限制适用于以下目录资源:用户设备和组织

    3 每个 开放扩展 都存储在 MAPI 命名属性 中,该属性是用户邮箱中的有限资源。 此限制适用于以下 Outlook 资源:邮件事件联系人

    使用工作或学校帐户登录时,可以管理所有扩展。 此外,使用个人 Microsoft 帐户登录时,可以管理以下资源的开放扩展:事件帖子消息联系人用户

    权限和特权

    若要管理资源实例上的任何扩展数据,你的应用需要用于从该资源实例读取或写入该资源实例的相同权限。 例如,在委托方案中,仅当应用被授予 User.ReadWrite.All 权限且已登录用户具有受支持的Microsoft Entra管理员角色时,应用才能更新任何用户的扩展数据。