注意
嵌套应用身份验证 (NAA) 仅在单页应用程序 (SPA) 中受支持,例如选项卡。
NAA 是一种新的身份验证协议,适用于嵌入在主机环境(如 Teams、Outlook 和 Microsoft 365)中的 SPA。 它简化了身份验证过程,以促进嵌套在受支持的主机应用中的应用之间的单一登录 (SSO) 。 NAA 模型支持主机应用的主要标识,其中包括嵌套应用的多个应用标识。 Microsoft 在 Teams 选项卡、个人应用和 Office 加载项中使用此模型。
与 On-Behalf-Of (OBO) 流相比,NAA 模型具有多项优势:
NAA 要求仅使用 MSAL.js 库。 无需在 TeamsJS) (Teams JavaScript 客户端库中使用
getAuthToken该函数。可以使用客户端代码中的访问令牌调用 Microsoft Graph 等服务作为 SPA。 不需要中间层服务器。
可对作用域 (权限) 使用增量和动态同意。
无需预先授权主机(如 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。 |
| 重新身份验证或条件访问 step-up auth | 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属性等效userObjectId于 TeamsJS 中。调用
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 或更高版本,并在 nestedAppAuthInfo .webApplicationInfo
{
"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\"]}}}"
}
]
}
}
重要
- 对于每个 NAA 令牌预取请求,在相应
nestedAppAuthInfo条目的可选clientId字段中指定代理或应用的 Microsoft Entra ID 注册客户端 ID。 如果提供,此值用于预提取该条目的令牌。 如果某个条目不包含clientId,主机将用作webApplicationInfo.id该条目的 NAA 令牌预取请求的客户端 ID。 -
webApplicationInfo.id是未指定 clientId 的条目的回退客户端 ID。 它不需要匹配每个入门级 clientId。 如果应用仅webApplicationInfo.id用于 NAA 令牌预提取,则该值必须与用于其实际 NAA 令牌请求的应用的 Microsoft Entra 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方法。 建议在acquireTokenSilent进行 API 调用之前调用应用,以获取有效的令牌。在某些情况下,使用该
acquireTokenSilent方法获取令牌的尝试会失败。 例如,如果具有 Microsoft Entra ID 的用户会话过期或应用用户acquireTokenSilent更改密码,则失败。 调用交互式获取令牌方法 (acquireTokenPopup) 。有一个回退:NAA 流提供跨 Microsoft 生态系统的兼容性。 但是,你的应用可能会出现在未更新以支持 NAA 的下层或旧客户端中。 在这种情况下,应用无法支持无缝 SSO,可能需要调用特殊 API 以便与用户交互以打开身份验证对话框。 有关详细信息,请参阅为 选项卡应用启用 SSO。
注意
如果使用的是非 Microsoft Entra 标识提供者,则不得使用 NAA,可以改用弹出身份验证。
支持 NAA:并非所有主机应用环境都支持 NAA。 若要验证当前客户端是否支持此功能,可以调用指定的 API 来确定其状态。 如果返回值为
trueNAA,则表示支持 NAA,而false表示不支持它。在多个环境中测试应用:如果应用预期可在 Web 视图和浏览器部署中运行,建议在这两个部署环境中测试应用,以确保其行为符合你的预期。 在浏览器中运行的某些 API 可能无法在 Web 视图中运行。
代码示例
| 示例名称 | Description | .NET | Node.js |
|---|---|---|---|
| 嵌套应用身份验证 | 此示例展示了Microsoft Entra Microsoft Teams 选项卡中的单一登录 (SSO) ,利用“代表 (OBO) ”流代表用户调用Microsoft图形 API。 | View | View |