Office 365 管理 API 入门

如果创建需要访问 Office 365 管理 API 等安全服务的应用程序,必须设法让安全服务知道应用程序是否有权访问它。 Office 365管理 API 使用 Microsoft Entra ID 提供身份验证服务,可用于向应用程序授予访问服务的权限。

有四个关键步骤:

  1. 在 Microsoft Entra ID 中注册应用程序。 若要允许应用程序访问Office 365管理 API,需要在 Microsoft Entra ID 中注册应用程序。 这样,便可为应用程序建立标识,并指定它访问 API 所需的权限级别。

  2. 获取 Office 365 租户管理员同意。 Office 365 租户管理员必须明确同意允许应用程序通过 Office 365 管理 API 访问管理员租户数据。 许可过程是基于浏览器的体验,它要求租户管理员登录到Microsoft Entra同意 UI 并查看应用程序请求的访问权限,然后授予或拒绝请求。 在同意授予后,UI 便会将用户重定向回应用程序,此时 URL 中包含授权代码。 应用程序对 Microsoft Entra ID 进行服务到服务调用,以将此授权代码交换为访问令牌,其中包含有关租户管理员和应用程序的信息。 必须从访问令牌中提取并存储租户 ID,以供日后使用。

  3. 从 Microsoft Entra ID 请求访问令牌。 使用 Microsoft Entra ID 中配置的应用程序凭据,应用程序会持续为已同意的租户请求额外的访问令牌,而无需进一步的租户管理员交互。 这些访问令牌称为“仅应用程序令牌”,因为它们不包含租户管理员的相关信息。

  4. 调用 Office 365 管理 API。 仅应用程序访问令牌被传递到 Office 365 管理 API,以验证和授权应用程序。

下图展示了获取同意和请求获取访问令牌的顺序。

管理 API 入门 - 授权流

重要

必须为你的 Office 365 组织启用统一审核日志记录,然后才能通过 Office 365 管理活动 API 访问数据。 可通过启用 Office 365 审核日志来实现此操作。 有关说明,请参阅打开或关闭 Office 365 审核日志搜索

如果你仅使用 Office 365 服务通信 API,则不需要启用统一审核日志记录。

在 Microsoft Entra ID 中注册应用程序

Office 365管理 API 使用 Microsoft Entra ID 为Office 365租户数据提供安全身份验证。 若要访问Office 365管理 API,需要在 Microsoft Entra ID 中注册应用,并在配置过程中指定应用访问 API 所需的权限级别。

先决条件

若要在 Microsoft Entra ID 中注册应用,需要Office 365订阅以及与Office 365订阅关联的 Azure 订阅。 可以从 Office 365 和 Azure 这两款产品的试用订阅入手。 有关详细信息,请参阅欢迎加入 Office 365 开发人员计划

使用 Azure 门户在 Microsoft Entra ID 中注册应用程序

拥有具有适当订阅的 Microsoft 租户后,可以在 Microsoft Entra ID 中注册应用程序。

  1. 使用具有想要使用的 Office 365 订阅的 Microsoft 租户凭据登录到 Azure 门户。 还可以通过显示在 Microsoft 365 管理中心 内左侧导航窗格中的链接访问 Azure 门户。

  2. 在左侧导航窗格中,选择Microsoft Entra ID (1) 。

    Azure 门户主页

  3. “Microsoft Entra ID”页上,选择“应用注册 (2) ”,然后选择“新建注册 (3) ”。

    Microsoft Entra ID 中的应用注册页

  4. 在“应用注册”页面,选择“新增注册”。

    将显示开始注册应用的新页面。

  5. 注册应用程序 页面中,执行以下操作:

    应用注册流程

    1. 命名应用。

    2. 选择可以使用应用并访问 API 的人员。

    3. 如果需要,请在身份验证后为用户重定向提供重定向 URL。

  6. 点击 注册 以注册新应用。

在 Microsoft Entra ID 中配置应用程序属性

注册应用程序后,必须指定几个重要属性来确定应用程序在Microsoft Entra ID中的工作方式,以及租户管理员将如何使用 Office 365 管理 API 授予允许应用程序访问其数据的许可。

有关一般Microsoft Entra应用程序配置的详细信息,请参阅应用程序对象属性

  1. 客户端 ID。 此值由 Microsoft Entra ID 自动生成。 在向租户管理员请求同意以及向Microsoft Entra ID请求仅限应用的令牌时,应用程序将使用此值。

  2. 应用程序为多租户。 此属性必须设置为“是”,这样租户管理员才能同意允许应用程序使用 Office 365 管理 API 访问管理员租户数据。 如果此属性设置为“否”,应用程序就只能访问你自己租户的数据。

  3. 回复 URL。 这是租户管理员在同意允许应用程序使用 Office 365 管理 API 访问管理员租户数据后重定向到的 URL。 可根据需要配置多个回复 URL。 Azure 会自动设置第一个回复 URL,以匹配你在创建应用程序时指定的登录 URL,但你可根据需要更改此值。

更改这些属性后,请务必选择“保存”

生成应用程序的新密钥

当交换访问令牌的授权代码时,会使用密钥(也称为 客户端密码)。

  1. Azure 门户的“Microsoft Entra ID”页上,选择“应用注册”,然后选择应用程序。

    选择刚刚注册的应用

  2. 在应用页面显示后,在左窗格中选择 证书和密码 (1)。 在此页面中,可以上传证书并新建客户端密码(2)。

    应用的“证书和密码”页面

  3. 证书和密码 (1)页面中,选择 新客户端密码 (2),键入说明并选择密钥的持续时间(3),然后选择 添加 (4)。

    创建客户端密码

  4. 创建客户端密码后,该值将显示在 客户端密码(2) 下。 点击剪贴板图标(3),以将客户端密码值复制到剪贴板。

    将客户端密码值复制到剪贴板并将其保存,以供之后使用

    重要

    Azure 仅在你最初生成客户端密码值时显示该值。 之后无法返回此页面并取回客户端密码值。 请确保将其复制并保存到安全位置,以便之后使用。

将 X.509 证书配置为启用服务到服务调用

在后台运行的应用程序(如守护程序或服务)可使用客户端凭据,以请求获取仅应用程序访问令牌,而无需在获取初始同意后重复请求获取租户管理员同意。

有关详细信息,请参阅使用客户端凭据执行服务到服务调用

在从 Microsoft Entra ID 请求仅限应用的访问令牌时,必须使用应用程序配置 X.509 证书作为客户端凭据。 此过程分为两步:

  • 获取 X.509 证书。 可使用自签名证书或由公共可信的证书颁发机构颁发的证书。

  • 将应用程序清单修改为,包含证书的指纹和公钥。

下面介绍了如何使用 Visual Studio 或 Windows SDK makecert 工具生成自签名证书,并将公钥导出到经过 base64 编码的文件中。

  1. 在命令行中运行下面的命令:

     makecert -r -pe -n "CN=MyCompanyName MyAppName Cert" -b 03/15/2015 -e 03/15/2017 -ss my -len 2048
    

    注意

    生成 X.509 证书时,请确保密钥长度至少为 2048。 无法将长度较短的密钥接受为有效密钥。

  2. 打开证书 MMC 管理单元,并连接到用户帐户。

  3. 在“个人”文件夹中查找新证书,并将公钥导出到 base64 编码文件中(例如,mycompanyname.cer)。 应用程序将使用此证书与Microsoft Entra ID通信,因此请确保你也保留对私钥的访问权限。

    注意

    可使用 Windows PowerShell 提取指纹和经过 base64 编码的公钥。 其他平台提供了用于检索证书属性的类似工具。

  4. 在Windows PowerShell提示符下,输入并运行以下内容:

     $cer = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2
     $cer.Import("mycer.cer")
     $bin = $cer.GetRawCertData()
     $base64Value = [System.Convert]::ToBase64String($bin)
     $bin = $cer.GetCertHash()
     $base64Thumbprint = [System.Convert]::ToBase64String($bin)
     $keyid = [System.Guid]::NewGuid().ToString()
    
  5. 存储 $base64Thumbprint$base64Value$keyid 的值,以供在下一组步骤中更新应用程序清单时使用。

    使用从证书提取的值和生成的密钥 ID,现在必须在 Microsoft Entra ID 中更新应用程序清单。

  6. 在 Azure 门户中,转到 应用注册>所有应用程序,选择应用程序,然后在左窗格中选择 清单

  7. 清单 页面(1)的顶部导航栏中,选择 下载 (2)。

    下载清单以便编辑

  8. 在编辑器中打开下载的清单,并将空的 keyCredentials 属性替换为以下 JSON:

       "keyCredentials": [
         {
             "customKeyIdentifier" : "$base64Thumbprint_from_above",
             "keyId": "$keyid_from_above",
             "type": "AsymmetricX509Cert",
             "usage": "Verify",
             "value": "$base64Value_from_above"
         }
     ],
    

    注意

    KeyCredentials 属性是一个集合,让为滚动更新方案上传多个 X.509 证书,或者为泄漏方案删除证书成为可能。

  9. 保存更改,并依次选择命令栏中的“管理清单”和“上传清单”,再浏览并选择更新后的清单文件以上传。

指定应用程序访问 Office 365 管理 API 所需的权限

最后,需要指定应用程序访问 Office 365 管理 API 所需的确切权限。 为此,请先向应用程序添加对 Office 365 管理 API 的访问权限,再指定所需的一项或多项权限。

  1. 在 Azure 门户中,转到 应用注册>所有应用程序,选择应用程序,然后在左窗格中选择 API 权限 (1)。 点击 添加权限 (2)以显示 请求 API 权限 (3)浮出控件页面。

    添加 API 权限

  2. Microsoft API 选项卡中,选择 Office 365 管理 API (4)。

    在 Microsoft API 选项卡中选择 Office 365 管理 API

  3. 在浮出控件页面中,选择应用所需的以下权限类型 (3),然后点击 添加权限

    选择应用的权限类型

    1. 委派权限。 允许客户端应用代表已登录用户执行操作,例如阅读电子邮件或修改用户的配置文件。

    2. 应用程序权限。 允许客户端应用在无用户交互或同意的情况下以自身身份进行身份验证的权限,例如后台服务使用的应用或守护进程应用。

  4. Office 管理 API 现在显示在应用需要其权限的应用程序列表中。 在 应用程序权限委派权限下,如果需要,请选择应用程序所需的权限。 若要详细了解每项权限,请参阅具体的 API 参考。

    应用的 API 权限

  5. 选择 为“租户名称”授予管理员许可,以同意授予应用的权限。

至此,应用程序已配置有使用 Office 365 管理 API 所需的权限。租户管理员必须显式授予应用程序这些权限,应用程序才能使用 API 访问管理员租户数据。 若要授予同意,租户管理员必须使用以下专门构造的 URL 登录到Microsoft Entra ID,他们可以在其中查看应用程序请求的权限。 如果使用 API 访问你自己租户的数据,便无需执行这一步。

https://login.windows.net/common/oauth2/authorize?response_type=code&resource=https%3A%2F%2Fmanage.office.com&client_id={your_client_id}&redirect_uri={your_redirect_url }

重定向 URL 必须与 Microsoft Entra ID 中为应用程序配置的回复 URL 之一匹配或子路径。

例如:

https://login.windows.net/common/oauth2/authorize?response_type=code&resource=https%3A%2F%2Fmanage.office.com&client_id=2d4d11a2-f814-46a7-890a-274a72a7309e&redirect_uri=http%3A%2F%2Fwww.mycompany.com%2Fmyapp%2F

可测试同意 URL,具体方法为将同意 URL 粘贴到浏览器中,并使用除用于注册应用程序的租户以外的租户的 Office 365 管理员凭据登录。 此时,可看到向应用程序授予 Office 管理 API 使用权限的请求。

“权限同意”页面

选择“接受”后,便会重定向到指定页,并且查询字符串中会有授权代码。

例如:

http://www.mycompany.com/myapp/?code=AAABAAAAvPM1KaPlrEqdFSB...

应用程序使用此授权代码从Microsoft Entra ID获取访问令牌,可从中提取租户 ID。 提取并存储租户 ID 后,可获取后续访问令牌,而无需请求租户管理员登录。

从 Microsoft Entra ID 请求访问令牌

可通过两种方法从 Microsoft Entra ID 请求访问令牌:

  • 授权代码授予流:让租户管理员明确授予同意,以向应用程序返回授权代码。 然后,应用程序用授权代码交换访问令牌。 必须使用这种方法,才能获取应用程序使用 API 访问租户数据所需的初始同意;并且必须有第一个访问令牌,才能获取并存储租户 ID。

  • 客户端凭据授予流:允许应用程序在旧版访问令牌到期时请求获取后续访问令牌,而无需请求租户管理员登录并明确授予同意。 必须对在初始租户管理员同意授予后在后台连续运行并调用 API 的应用程序使用这种方法。

使用授权代码请求获取访问令牌

租户管理员授予同意后,当Microsoft Entra ID将租户管理员重定向到指定的 URL 时,应用程序会收到一个授权代码作为查询字符串参数。

http://www.mycompany.com/myapp/?code=AAABAAAAvPM1KaPlrEqdFSB...

应用程序创建 HTTP REST POST 以Microsoft Entra ID交换访问令牌的授权代码。 由于租户 ID 尚未知,因此 POST 会被发送到“常用”终结点,即 URL 中没有嵌入租户 ID:

https://login.windows.net/common/oauth2/token

POST 正文包含以下内容:

resource=https%3A%2F%2Fmanage.office.com&client_id=a6099727-6b7b-482c-b509-1df309acc563 &redirect_uri= http%3A%2F%2Fwww.mycompany.com%2Fmyapp%2F &client_secret={your_client_key}&grant_type=authorization_code&code= AAABAAAAvPM1KaPlrEqdFSB...

示例请求

POST https://login.windows.net/common/oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: login.windows.net
Content-Length: 944

resource=https%3A%2F%2Fmanage.office.com&client_id=a6099727-6b7b-482c-b509-1df309acc563 &redirect_uri= http%3A%2F%2Fwww.mycompany.com%2Fmyapp%2F &client_secret={your_client_key}&grant_type=authorization_code&code=AAABAAAAvPM1KaPlrEqdFSB...

响应正文包含多个属性,包括访问令牌。

示例响应

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 3265

{"expires_in":"3599","token_type":"Bearer","scope":"ActivityFeed.Read ActivityReports.Read ServiceHealth.Read","expires_on":"1438290275","not_before":"1438286375","resource":"https://manage.office.com","access_token":"eyJ0eX...","refresh_token":"AAABAAA...","id_token":"eyJ0eXAi..."}

返回的访问令牌是 JWT 令牌,其中既包含授予同意的管理员的相关信息,也包含请求获取访问权限的应用程序的相关信息。 下面的示例展示了未编码的令牌。 应用程序必须从此令牌中提取并存储租户 ID “tid”,这样才能在访问令牌到期时用它请求获取其他访问令牌,而无需与管理员有进一步交互。

示例令牌

{
  "aud": "https://manage.office.com",
  "iss": "https://sts.windows.net/41463f53-8812-40f4-890f-865bf6e35190/",
  "iat": 1427246416,
  "nbf": 1427246416,
  "exp": 1427250316,
  "ver": "1.0",
  "tid": "41463f53-8812-40f4-890f-865bf6e35190",
  "amr": [
    "pwd"
  ],
  "oid": "1cef1fdb-ff52-48c4-8e4e-dfb5ea83d357",
  "upn": "admin@contoso.onmicrosoft.com",
  "puid": "1003BFFD8EC47CA6",
  "sub": "7XpD5OWAXM1OWmKiVKh1FOkKXV4N3OSRol6mz1pxxhU",
  "given_name": "John",
  "family_name": "Doe",
  "name": "Contoso, Inc.",
  "unique_name": "admin@contoso.onmicrosoft.com",
  "appid": "a6099727-6b7b-482c-b509-1df309acc563",
  "appidacr": "1",
  "scp": "ActivityFeed.Read ServiceHealth.Read",
  "acr": "1"
}

使用客户端凭据请求获取访问令牌

租户 ID 已知后,应用程序可以对Microsoft Entra ID进行服务到服务调用,以便在令牌过期时请求其他访问令牌。 这些令牌仅包含发出请求的应用程序的相关信息,并不包含最初授予同意的管理员的相关信息。 若要执行服务到服务调用,应用程序必须使用 X.509 证书创建客户端断言(形式为经过 base64 编码的 SHA256 签名 JWT 持有者令牌)。

在 .NET 中开发应用程序时,可以使用 Microsoft 身份验证库 (MSAL) 创建客户端断言。 其他开发平台应该有类似的库。

未编码的 JWT 令牌由具有以下属性的头和有效负载组成。

HEADER:

{
  "alg": "RS256",
  "x5t": "{thumbprint of your X.509 certificate used to sign the token",
}

PAYLOAD:

{
  "aud": "https://login.windows.net/{tenantid}/oauth2/token",
  "iss": "{your app client ID}",
  "sub": "{your app client ID}",
  "jti": "{random GUID}",
  "nbf": "{epoch time, before which the token is not valid}",
  "exp": "{epoch time, after which the token is not valid}"
}

示例 JWT 令牌

HEADER:

{
  "alg": "RS256",
  "x5t": "YyfshJC3rPQ-kpGo5dUaiY5t3iU",
}

PAYLOAD:

{
  "aud": "https://login.windows.net/41463f53-8812-40f4-890f-865bf6e35190/oauth2/token",
  "iss": "a6099727-6b7b-482c-b509-1df309acc563",
  "sub": "a6099727-6b7b-482c-b509-1df309acc563",
  "jti": "0ce254c4-81b1-4a2e-8436-9a8c3b49dfb9",
  "nbf": 1427248048,
  "exp": 1427248648,
}

然后,客户端断言作为服务到服务调用的一部分传递给 Microsoft Entra ID,以请求访问令牌。 使用客户端凭据请求获取访问令牌时,请将 HTTP POST 发送到租户专用终结点,即 URL 中已嵌入先前提取和存储的租户 ID。

https://login.windows.net/{tenantid}/oauth2/token

POST 正文包含以下内容:

resource=https%3A%2F%2Fmanage.office.com&client_id={your_app_client_id}&grant_type=client_credentials&client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion={encoded_signed_JWT_token}

示例请求

POST https://login.windows.net/41463f53-8812-40f4-890f-865bf6e35190/oauth2/token HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Host: login.windows.net
Content-Length: 994

resource=https%3A%2F%2Fmanage.office.com&client_id= a6099727-6b7b-482c-b509-1df309acc563&grant_type=client_credentials &client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&client_assertion=eyJhbGciOiJSUzI1NiIsIng1dCI6Ill5ZnNoSkMzclBRLWtwR281ZFVhaVk1dDNpVSJ9.eyJhdWQiOiJodHRwczpcL1wvbG9naW4ud2luZG93cy5uZXRcLzQxNDYzZjUzLTg4MTItNDBmNC04OTBmLTg2NWJmNmUzNTE5MFwvb2F1dGgyXC90b2tlbiIsImV4cCI6MTQyNzI0ODY0OCwiaXNzIjoiYTYwOTk3MjctNmI3Yi00ODJjLWI1MDktMWRmMzA5YWNjNTYzIiwianRpIjoiMGNlMjU0YzQtODFiMS00YTJlLTg0MzYtOWE4YzNiNDlkZmI5IiwibmJmIjoxNDI3MjQ4MDQ4LCJzdWIiOiJhNjA5OTcyNy02YjdiLTQ4MmMtYjUwOS0xZGYzMDlhY2M1NjMifQ.vfDrmCjiXgoj2JrTkwyOpr-NOeQTzlXQcGlKGNpLLe0oh4Zvjdcim5C7E0UbI3Z2yb9uKQdx9G7GeqS-gVc9kNV_XSSNP4wEQj3iYNKpf_JD2ikUVIWBkOg41BiTuknRJAYOMjiuBE2a6Wyk-vPCs_JMd7Sr-N3LiNZ-TjluuVzWHfok_HWz_wH8AzdoMF3S0HtrjNd9Ld5eI7MVMt4OTpRfh-Syofi7Ow0HN07nKT5FYeC_ThBpGiIoODnMQQtDA2tM7D3D6OlLQRgLfI8ir73PVXWL7V7Zj2RcOiooIeXx38dvuSwYreJYtdphmrDBZ2ehqtduzUZhaHL1iDvLlw

响应与之前几乎相同,区别在于令牌不包含相同的属性,因为它不包含授予同意的管理员的属性。

示例响应

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 1276

{"token_type":"Bearer","expires_in":"3599","expires_on":"1431659094","not_before":"1431655194","resource":"https://manage.office.com","access_token":"eyJ0eXAiOiJKV1QiL..."}

示例访问令牌

{
  "aud": "https://manage.office.com",
  "iss": "https://sts.windows.net/41463f53-8812-40f4-890f-865bf6e35190/",
  "iat": 1431655194,
  "nbf": 1431655194,
  "exp": 1431659094,
  "ver": "1.0",
  "tid": "41463f53-8812-40f4-890f-865bf6e35190",
  "roles": [
    "ServiceHealth.Read",
    "ActivityFeed.Read"
  ],
  "oid": "67cb0334-e242-4783-8028-0f39132fb5ad",
  "sub": "67cb0334-e242-4783-8028-0f39132fb5ad",
  "idp": "https://sts.windows.net/41463f53-8812-40f4-890f-865bf6e35190/",
  "appid": "a6099727-6b7b-482c-b509-1df309acc563",
  "appidacr": "1"
}

生成应用程序

现在,你已在 Microsoft Entra ID 中注册应用并为其配置了必要的权限,现在可以生成应用了。 下面是设计和生成应用时要考虑的一些关键方面。

  • 同意体验。 若要获得客户的同意,必须使用前面所述的专门构造的 URL 在浏览器中将他们定向到Microsoft Entra网站,并且必须有一个网站,Microsoft Entra ID在管理员同意后会重定向到该网站。 此网站必须从 URL 中提取授权代码,并用它来请求获取可从中获取租户 ID 的访问令牌。

  • 将租户 ID 存储在系统中。 从 Microsoft Entra ID 请求访问令牌以及调用 Office 管理 API 时,需要执行此操作。

  • 管理访问令牌。 你需要一个根据需要请求和管理访问令牌的组件。 如果应用程序定期调用 API,可按需请求获取令牌;或如果应用程序连续调用 API 来检索数据,可定期(例如,每 45 分钟)请求获取一次令牌。

  • 实现 Webhook 侦听器。 根据所使用的特定 API 的需要。

  • 数据检索和存储。 需要有检索每个租户的数据的组件,检索方式可以是使用连续轮询,也可以是响应 Webhook 通知,具体视要使用的特定 API 而定。