嵌套应用身份验证和 Outlook 旧版令牌弃用常见问题解答

Exchange 用户标识令牌回调令牌 已弃用,将从 2025 年 2 月开始关闭。 建议将使用旧版 Exchange 令牌的 Outlook 加载项移动到嵌套应用身份验证。

常规常见问题解答

什么是 NAA) (嵌套应用身份验证?

嵌套应用身份验证为嵌套在受支持的 Microsoft 应用程序(如 Outlook)中的应用程序启用单一登录 (SSO) 。 与现有的完全信任身份验证模型和代理流相比,NAA 在应用体系结构中提供了更好的安全性和更大的灵活性,从而支持创建丰富的客户端驱动应用程序。 有关详细信息,请参阅 使用嵌套应用身份验证在 Office 外接程序中启用 SSO

关闭旧版 Exchange 联机令牌时间线是什么?

Microsoft从 2025 年 2 月开始关闭旧版 Exchange 联机令牌。 从现在到 2025 年 2 月,现有租户和新租户将不受影响。 如果租户和外接程序尚未迁移到 NAA,我们将为管理员提供可重新启用 Exchange 令牌的工具。 有关详细信息 ,请参阅是否可以重新打开旧版令牌?

日期 旧令牌状态
2025 年 2 月 所有租户的旧令牌已关闭。 管理员可以通过 PowerShell 重新启用旧令牌。
2025 年 6 月 所有租户的旧令牌已关闭。 管理员无法再通过 PowerShell 重新启用旧令牌,必须联系 Microsoft 了解任何异常。
2025 年 10 月 所有租户的旧令牌已关闭。 不再允许出现异常。

NAA 何时对我的频道正式发布?

NAA 的正式发布 (正式发布) 日期取决于你正在使用的频道。

日期 NAA 正式发布 (GA)
2024 年 10 月 NAA 在当前频道中正式发布。
2024 年 11 月 NAA 将在每月企业频道中正式发布。
2025 年 1 月 NAA 将在 Semi-Annual 频道正式发布。
2025 年 6 月 NAA 将在 Semi-Annual 扩展频道中正式发布。

是否可以重新打开旧版令牌?

从 2024 年 10 月 30 日至 11 月中旬,我们将通过 PowerShell 为 365 Microsoft管理员推出新工具,以打开或关闭租户中的旧 Exchange 令牌。 如果发现需要重新启用旧版 Exchange 令牌,可以使用 PowerShell cmdlet 执行此操作。 该工具还会报告是否有任何加载项在过去 28 天内使用旧令牌。 该工具在所有租户中可用后,我们将更新此常见问题解答,其中包含其他信息。

Outlook 加载项迁移常见问题解答

为什么Microsoft使 Outlook 加载项迁移?

使用 Entra ID 令牌切换到 Microsoft Graph 是 Outlook 和 Exchange 客户安全性的一大改进。 Entra ID (以前为 Azure Active Directory) 是基于云的领先标识和访问管理服务。 客户可以利用零信任功能,例如条件访问、MFA 要求、持续令牌监视、实时安全启发法,以及旧版 Exchange 令牌无法提供的更多功能。 客户将重要的业务数据存储在 Exchange 中,因此我们必须确保此数据受到保护。 迁移整个 Outlook 生态系统以将 Entra ID 令牌与 Microsoft Graph 结合使用可极大地提高客户数据的安全性。

我可以选择退出吗?

如果租户和外接程序尚未迁移到 NAA,我们将为管理员提供可重新启用 Exchange 令牌的工具。 有关详细信息 ,请参阅是否可以重新打开旧版令牌? 。 但是,在 2025 年 6 月,旧版Exchange Online令牌将关闭,如果没有Microsoft授予的特定例外,你将无法重新打开它们。 在 2025 年 10 月,无法打开旧版Exchange Online令牌,并且会为所有租户禁用这些令牌。 有关此工具的详细信息可用时,我们将更新此常见问题解答。

我的 Outlook 加载项是否必须迁移到 NAA?

不正确。 尽管 NAA 为用户提供了最佳的身份验证体验和组织的最佳安全状况,但 Outlook 加载项不必使用 NAA。 如果加载项未使用旧版 Exchange 令牌,则它们不会受到弃用 Exchange 令牌的影响。 使用 MSAL.js 或其他依赖于 Entra ID 的 SSO 方法的加载项将继续工作。

如何实现知道我的 Outlook 外接程序是否依赖于旧版令牌?

我们将为过去 28 天内使用旧版 Exchange 联机令牌的任何外接程序报告应用 ID 的管理员提供工具。 在本常见问题解答中,我们将在工具准备就绪时提供详细信息。 有关详细信息 ,请参阅是否可以重新打开旧版令牌?

若要了解外接程序是否使用旧版 Exchange 用户标识令牌和回调令牌,请在代码中搜索对以下 API 的调用。

  • makeEwsRequestAsync
  • getUserIdentityTokenAsync
  • getCallbackTokenAsync

如果外接程序调用这些 API 中的任何一个,则应采用 NAA 并迁移到使用 Entra ID 令牌来访问 Microsoft Graph。

哪些 Outlook 加载项在范围内?

许多主要加载项都在范围内。 如果外接程序使用 EWS 或 Outlook REST 访问Exchange Online资源,则几乎可以肯定需要从旧版 Outlook 令牌迁移到 NAA。 如果你的外接程序只用于 Exchange 本地 (例如 Exchange 2019) ,则不受此更改的影响。

如果我不迁移到 NAA,我的 Outlook 加载项会发生什么情况?

如果不将 Outlook 加载项迁移到 NAA,它们将在 Exchange Online 中停止按预期工作。 根据上表) 关闭 Exchange 令牌 (时,Exchange Online将阻止旧令牌颁发。 任何使用旧令牌的外接程序都无法访问 Exchange 联机资源。 如果外接程序仅在本地工作,或者外接程序位于弃用路径上,则可能不需要更新。 但是,通过 EWS 或 Outlook REST 访问 Exchange 资源的大多数加载项必须迁移才能继续按预期运行。

如何实现将 Outlook 加载项迁移到 NAA?

若要在 Outlook 加载项中支持 NAA,请参阅以下文档和示例。

作为管理员,如何知道我的组织中的哪些加载项需要更新?

我们将为过去 28 天内使用旧版 Exchange 联机令牌的任何外接程序报告应用 ID 的管理员提供工具。 在本常见问题解答中,我们将在工具准备就绪时提供详细信息。 有关详细信息 ,请参阅是否可以重新打开旧版令牌?

加载项可以使用旧版 Exchange 令牌通过 EWS 或 Outlook REST API 从 Exchange 获取资源。 有时,加载项需要 Exchange 资源用于某些用例,而不是其他用例,因此很难确定加载项是否需要更新。 我们建议联系加载项开发人员和所有者,询问他们的外接程序代码是否引用了以下 API。

  • makeEwsRequestAsync
  • getUserIdentityTokenAsync
  • getCallbackTokenAsync

如果你依赖独立软件供应商 (ISV) 为您的加载项,我们建议你尽快与他们联系,以确认他们有转移旧 Exchange 令牌的计划和时间线。 ISV 开发人员应直接与其Microsoft联系人联系,询问问题,以确保他们已准备好结束 Exchange 旧版令牌。 如果你依赖于组织中的开发人员,我们建议你要求他们查看有关弃用 Outlook 外接程序的旧Exchange Online令牌博客汇报,并在 OfficeDev/office-js GitHub 问题网站上向 Outlook 扩展性 PM 团队提出任何问题。

如何实现跟上最新指南?

我们将更新此常见问题解答,因为有新信息可用。 我们将在 Office 加载项社区通话M365 开发人员博客上分享更多指导。 最后,可以在 OfficeDev/office-js GitHub 问题网站上提出有关 NAA 和旧版Exchange Online令牌弃用的问题。 请在标题中放入“NAA”,以便我们可以对问题进行分组和确定优先级。

开发人员故障排除问题

NAA 未提供 SSO,并不断提示用户登录

当 NAA 在 Outlook 客户端中不可用时,可能会发生这种情况。 如果在 Windows 上,检查使用的是 Beta 频道或当前频道 (预览版) 。 需要加入 Microsoft 365 预览体验计划 才能切换到这些频道。 如果 NAA 可用,检查的一种好方法是使用以下代码片段检查要求集。 Office.context.requirements.isSetSupported("NestedAppAuth")

如何实现从 MSAL 和 NAA 获取更多调试信息?

初始化可嵌套的公共客户端应用程序时,使用以下代码在 msalConfig 中启用调试信息。 这会将其他详细信息记录到控制台。

const msalConfig = {
  auth: {...},
  system: {
    loggerOptions: {
      logLevel: LogLevel.Verbose,
      loggerCallback: (level, message, containsPii) => {
        switch (level) {
          case LogLevel.Error:
            console.error(message);
            return;
          case LogLevel.Info:
            console.info(message);
            return;
          case LogLevel.Verbose:
            console.debug(message);
            return;
          case LogLevel.Warning:
            console.warn(message);
            return;
        }
      },
    }
  }
};