注意
仅在单页应用程序 (SPA) (如选项卡)中支持嵌套应用身份验证 (NAA) 。
NAA 是嵌入主机环境(如 Teams、Outlook 和 Microsoft 365)中的 SPA 的新身份验证协议。 它简化了身份验证过程,以便跨嵌套在受支持的主机应用中的应用 (SSO) 单一登录。 NAA 模型支持主机应用的主要标识,其中包含嵌套应用的多个应用标识。 Microsoft在 Teams 选项卡、个人应用和 Office 加载项中使用此模型。
NAA 模型比代表 (OBO) 流具有多个优势:
NAA 要求你仅使用 MSAL.js 库。 无需在 TeamsJS) (Teams JavaScript 客户端库中使用
getAuthToken函数。可以使用来自客户端代码的访问令牌(作为 SPA)调用 Microsoft Graph 等服务。 无需使用中间层服务器。
可以对范围使用增量和动态许可 (权限) 。
无需预授权主机(例如 Teams 或 Microsoft 365)来调用终结点。
下表概述了 Teams Microsoft Entra SSO 与 NAA 之间的差异:
开发所需的步骤 传统 Teams Entra SSO Naa 公开重定向 URI 必需 必需 在 Microsoft Entra ID 中注册 API 必需 在 Microsoft Entra ID 中定义自定义范围 必需 授权 Teams 客户端应用 必需 修改应用清单 (以前称为 Teams 应用清单) 必需 推荐* 通过 TeamsJS SDK 获取访问令牌 必需 请求用户同意以获得更多权限 必需 在服务器上执行 OBO 交换 必需 IT 管理员可能会在 Microsoft Entra ID 中阻止应用或仅同意应用的特定权限。 若要避免这种情况,必须在应用清单中包含应用 ID 和默认资源,以便管理员在 Teams 管理中心批准权限。
NAA 的用例
| 应用场景 | 说明 |
|---|---|
| 同意 SSO (和其他权限) | Tom 是 Contoso 设计团队的新成员,需要使用 Teams 会议中的 Contoso 应用来协作处理白板。 首次使用时,对话框会提示 Tom 授予权限,包括读取其头像 (User.Read) 的个人资料。 同意后,Tom 可以在将来的跨设备会议中无缝使用 Contoso。 |
| 重新身份验证或条件访问升级身份验证 | Tom 在澳大利亚工作时遇到条件访问触发器,需要多重身份验证 (MFA) 才能访问 Teams 中的 Contoso。 一个对话框通知 Tom 需要进行更多验证,引导他们完成 MFA 过程以继续使用 Contoso。 |
| 错误 | 由于检索帐户信息时出现问题,Tom 面临 Contoso 登录错误。 Tom 遇到提示重新进行身份验证的重试按钮。 但是,他们发现系统管理员已限制对 Contoso 的访问权限。 |
配置 NAA
若要配置嵌套身份验证,请执行以下步骤:
注册 SPA
必须在 Azure 门户 上为加载项创建Microsoft Entra ID应用注册。 应用注册必须具有名称、支持的帐户类型和 SPA 重定向。 注册应用后,Azure 门户会生成Microsoft Entra应用注册 ID。 如果外接程序需要除 NAA 和 SSO 以外的其他应用注册,请参阅 注册单页应用程序。
添加受信任的代理
若要配置嵌套应用身份验证,应用必须主动配置应用的重定向 URI。 重定向 URI 向Microsoft 标识平台指示支持主机可以中转应用。 应用的重定向 URI 必须是 单页应用程序 类型,并且符合以下方案:
brk-multihub://<your_domain>
其中:
-
brk-multihub使身份验证可由配置为运行的任何Microsoft 365 支持的主机(例如 Teams、Outlook 或 Microsoft365.com)中转。 - < > your_domain是托管应用的完全限定域名。 例如 ,brk-multihub://contoso.com。
域必须仅包含源,而不能包含其子路径。 例如:
✔️ brk-multihub://myapp.teams.microsoft.com
❌ brk-multihub://myapp.teams.microsoft.com/go
有关将 Teams 应用升级为在 Outlook 和 Microsoft365.com 中运行的详细信息,请参阅 跨 Microsoft 365 扩展 Teams 应用。
初始化公共客户端应用
注意
若要确保身份验证成功,请在初始化 MSAL 之前初始化 TeamsJS。
根据需要初始化 MSAL 并获取公共客户端应用的实例以获取访问令牌。
import {
AccountInfo,
IPublicClientApplication,
createNestablePublicClientApplication,
} from "@azure/msal-browser";
const msalConfig = {
auth: {
clientId: "your_client_id",
authority: "https://login.microsoftonline.com/{your_tenant_id}",
supportsNestedAppAuth: true
},
};
let pca: IPublicClientApplication;
export function initializePublicClient() {
console.log("Starting initializePublicClient");
return createNestablePublicClientApplication(msalConfig).then(
(result) => {
console.log("Client app created");
pca = result;
return pca;
}
);
}
获取第一个令牌
MSAL.js 通过嵌套应用身份验证获取的令牌将为Microsoft Entra应用注册 ID 颁发。 MSAL.js 处理用户身份验证的令牌获取。 它尝试以无提示方式获取访问令牌。 如果这不成功,它会提示用户同意。 然后,该令牌用于调用Microsoft图形 API或其他Microsoft Entra ID受保护的资源。 与 OBO 流不同,无需预授权主机来调用终结点。
若要获取令牌,请执行以下步骤:
使用 MSAL.js 获取应用 ID 的令牌。 有关详细信息,请参阅 获取和使用访问令牌。
使用
getActiveAccountAPI 验证是否有活动帐户来调用publicClientApplication。 如果没有活动帐户,请尝试使用 其他筛选器参数(如tenantID、homeAccountId和loginHint)从上下文接口检索缓存getAccount中的帐户。注意
属性
homeAccountId等效于userObjectIdTeamsJS 中。调用
publicClientApplication.acquireTokenSilent(accessTokenRequest)以无提示方式获取令牌,无需用户交互。accessTokenRequest指定请求访问令牌的范围。 NAA 支持增量和动态同意。 确保始终请求代码完成其任务所需的最小范围。如果没有可用的帐户,MSAL.js 将
InteractionRequiredAuthError返回 。 调用publicClientApplication.acquireTokenPopup(accessTokenRequest)以显示用户的交互式对话。acquireTokenSilent如果令牌过期或用户未同意所有请求的范围,则可能会失败。以下代码片段显示了访问令牌的示例:
// MSAL.js exposes several account APIs, logic to determine which account to use is the responsibility of the developer const account = publicClientApplication.getActiveAccount(); const accessTokenRequest = { scopes: ["user.read"], account: account, }; publicClientApplication .acquireTokenSilent(accessTokenRequest) .then(function (accessTokenResponse) { // Acquire token silent success let accessToken = accessTokenResponse.accessToken; // Call your API with token callApi(accessToken); }) .catch(function (error) { //Acquire token silent failure, and send an interactive request if (error instanceof InteractionRequiredAuthError) { publicClientApplication .acquireTokenPopup(accessTokenRequest) .then(function (accessTokenResponse) { // Acquire token interactive success let accessToken = accessTokenResponse.accessToken; // Call your API with token callApi(accessToken); }) .catch(function (error) { // Acquire token interactive failure console.log(error); }); } console.log(error); });
调用 API
收到令牌后,使用它调用 API。 这可确保使用有效的令牌调用 API,以向服务器发出经过身份验证的请求。
以下示例演示如何向Microsoft图形 API发出经过身份验证的请求,以访问Microsoft 365 数据:
var headers = new Headers();
var bearer = "Bearer " + access_token;
headers.append("Authorization", bearer);
var options = {
method: "GET",
headers: headers
};
var graphEndpoint = "<https://graph.microsoft.com/v1.0/me>";
fetch(graphEndpoint, options)
.then(function (response) {
//do something with response
});
用于嵌套应用身份验证的令牌预提取 (NAA)
为了提高性能并减少身份验证延迟,嵌套应用身份验证 (NAA) 支持令牌预提取。 此功能使主机能够在应用启动之前主动获取身份验证令牌,从而更快地访问受保护的资源。
如何启用令牌预提取
若要启用令牌预提取,请将 Teams 应用清单更新到版本 1.22 或更高版本,并在 中包含 webApplicationInfo部分nestedAppAuthInfo。
{
"webApplicationInfo": {
"id": "33333ddd-0000-0000-0000-88888757bbbb",
"resource": "api://app.com/botid-33333ddd-0000-0000-0000-88888757bbbb",
"nestedAppAuthInfo": [
{
"redirectUri": "brk-multihub://app.com",
"scopes": ["openid", "profile", "offline_access"],
"claims": "{\"access_token\":{\"xms_cc\":{\"values\":[\"CP1\"]}}}"
}
]
}
}
重要
- webApplicationInfo.id 的值必须与应用Microsoft Entra ID注册的客户端 ID 匹配。 这是应用在发出实际 NAA 令牌请求时使用的客户端 ID。 主机使用此 ID 启动令牌预提取过程。
- webApplicationInfo.id 中的值和 nestedAppAuthInfo 中的所有字段必须与应用的运行时 NAA 令牌请求中使用的参数完全匹配。 任何不匹配(例如范围、重定向 URI 或声明的差异)都会阻止主机从缓存中提供令牌。
- 预提取令牌存储在内存中,持续时间较短,只能在应用初始加载期间使用。 如果应用稍后尝试提取令牌(例如响应用户操作),则预提取的令牌可能不再可用。 在这种情况下,应用必须使用标准身份验证流启动新的令牌请求。
运作方式
启用令牌预提取后,主机环境会尝试在呈现应用之前获取和缓存所需的令牌。 这些令牌存储在内存中,并在启动时立即提供给应用。
此行为类似于旧版 Teams SSO 模型中的预提取功能,该模型在 getAuthToken 选项卡加载期间自动触发了 API。 使用嵌套应用身份验证 (NAA) ,此功能通过清单配置引入,无需进行后端令牌交换即可提高性能。
NAA 中令牌预提取的优点
- 通过减少应用启动期间的身份验证延迟来提高性能
- 跨嵌套应用启用单一登录 (SSO) ,无需重复登录
注意
令牌预提取目前仅在 Microsoft Teams Web 和桌面客户端中受支持。
最佳做法
尽可能使用无提示身份验证:MSAL.js 提供了
acquireTokenSilent方法,该方法通过在不提示用户的情况下发出无提示令牌请求来处理令牌续订。 方法首先在浏览器存储中查找有效的缓存令牌。 如果找不到,库会向Microsoft Entra ID发出无提示请求,如果存在活动用户会话 (由Microsoft Entra域) 上的浏览器中设置的 Cookie 确定,Microsoft Entra ID将返回新的令牌。 库不会自动调用acquireTokenSilent方法。 建议在进行 API 调用acquireTokenSilent之前在应用中调用 以获取有效令牌。在某些情况下,尝试使用 方法获取令牌失败
acquireTokenSilent。 例如,当应用用户Microsoft Entra ID过期的用户会话或密码更改时,acquireTokenSilent会失败。 ()acquireTokenPopup调用交互式获取令牌方法。具有回退:NAA 流提供跨Microsoft生态系统的兼容性。 但是,你的应用可能显示在未更新为支持 NAA 的下层客户端或旧版客户端中。 在这种情况下,你的应用不能支持无缝 SSO,你可能需要调用特殊的 API 来与用户交互以打开身份验证对话框。 有关详细信息,请参阅 为选项卡应用启用 SSO。
注意
如果使用非Microsoft Entra标识提供者,则不得使用 NAA,可以改用弹出身份验证。
对 NAA 的支持:并非所有主机应用环境都支持 NAA。 若要验证当前客户端是否支持此功能,可以调用指定的 API 来确定其状态。 返回值 表示
true对 NAA 的支持,但false表示不支持 NAA。在多个环境中测试应用:如果你的应用预期同时在 Web 视图和浏览器部署中运行,我们建议在这两个部署环境中测试你的应用,以确保其按预期运行。 浏览器中运行的某些 API 可能无法在 Web 视图中运行。
代码示例
| 示例名称 | Description | .NET | Node.js |
|---|---|---|---|
| 嵌套应用身份验证 | 此示例演示了 Microsoft Teams 选项卡中Microsoft Entra单一登录 (SSO) ,并利用代表 (OBO) 流来代表用户调用Microsoft图形 API。 | View | View |