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

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。

开发者体验

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

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

以下示例演示如何使用 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
            }
        }
    ]
}

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

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

15 个扩展属性已在 Microsoft Graph 中预定义,无法更改其属性名称。 因此,不能将自定义名称(如 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,则也会删除架构扩展对象。
    • 若要更新任何属性,必须在请求正文中指定 所有 属性。 否则,Microsoft Graph 会将未指定的属性更新为 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
  • Bruno 的用户对象不能有 open 扩展属性。
  • Alex 的用户对象可以具有名为 socialSettings 的 开放扩展,该扩展具有五个属性: 主题颜色语言字体fontSize

创建开放扩展

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

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 属性。 xboxGamerTag 属性的值正在更新,而 linkedInProfile 属性将保持不变。 此请求还会删除未指定的 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
可以存储集合
绑定到“所有者”应用程序
管理方式 Microsoft Graph
Exchange 管理中心
Microsoft Graph Microsoft Graph Microsoft Graph
使用 AD Connect 将数据从本地同步到扩展 是,对于用户
使用自定义扩展属性和数据创建 动态成员资格规则
可用于自定义令牌声明 是 (12)
在 Azure AD B2C 中提供
限制
  • 每个用户或设备资源实例 15 个预定义属性
  • 每个资源实例 100 个扩展值
  • 每个所有者应用最多五个定义
  • 每个资源实例 100 个扩展值(仅限目录对象)
  • 每个资源实例每个创建者应用两个开放扩展2
  • 最大 每个打开的扩展 2 Kb2
  • 对于 Outlook 资源,每个开放扩展都存储在 MAPI 命名属性3
  • 注意

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

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

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

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

    权限和特权

    管理该资源实例上的任何扩展数据时,还需要应用对资源实例进行读取或写入所需的相同权限。 例如,在委派方案中,如果应用被授予 User.ReadWrite.All 权限且已登录用户具有受支持的Microsoft Entra管理员角色,则应用只能更新任何用户的扩展数据。