适用于:
外部租户(了解详细信息)
基于角色的访问控制 (RBAC) 是一种在应用程序中强制进行授权的机制。 Microsoft Entra 外部 ID 允许为应用程序定义应用程序角色,并将这些角色分配给用户和组。 分配给用户或组的角色定义其对应用程序中资源和操作的访问级别。 当外部 ID 为经过身份验证的用户颁发安全令牌时,它包括你在安全令牌的角色声明中为用户或组分配的角色的名称。
还可配置外部租户,以返回用户的组成员身份。 然后,开发人员可使用安全组在应用程序中实现 RBAC,其中特定组中用户的成员身份会被解释为他们的角色成员身份。
将用户和组分配到角色后,角色声明将在安全令牌中发出。 但是,若要在安全令牌中发出 组 成员身份声明,需要在外部租户中执行其他配置。
本文介绍如何在 Node.js Web 应用的安全令牌中以声明的形式接收用户角色或组成员身份(或两者)。
先决条件
如果尚未这样做,请完成对应用程序使用基于角色的访问控制一文中的步骤。 本文介绍如何为应用程序创建角色、如何将用户和组分配给这些角色、如何将成员添加到组、如何将组声明添加到安全令牌。 详细了解 ID 令牌和访问令牌。
如果尚未这样做,请完成在你自己的 Node.js Web 应用程序中登录用户中的步骤
在 Node.js Web 应用中接收组和角色声明
配置外部租户后,可以在客户端应用中检索 角色 和 组 声明。 角色和组声明都在 ID 令牌和访问令牌中,但要在客户端实现授权,你的客户端应用只需在 ID 令牌中检查这些声明。 API 应用还可以在收到访问令牌时检索这些声明。
检查角色声明值,如以下代码片段示例所示:
const msal = require('@azure/msal-node');
const { msalConfig, TENANT_SUBDOMAIN, REDIRECT_URI, POST_LOGOUT_REDIRECT_URI } = require('../authConfig');
...
class AuthProvider {
...
async handleRedirect(req, res, next) {
const authCodeRequest = {
...req.session.authCodeRequest,
code: req.body.code, // authZ code
codeVerifier: req.session.pkceCodes.verifier, // PKCE Code Verifier
};
try {
const msalInstance = this.getMsalInstance(this.config.msalConfig);
const tokenResponse = await msalInstance.acquireTokenByCode(authCodeRequest, req.body);
let roles = tokenResponse.idTokenClaims.roles;
//Check roles
if (roles && roles.includes("Orders.Manager")) {
//This user can view the ID token claims page.
res.redirect('/id');
}
//User can only view the index page.
res.redirect('/');
} catch (error) {
next(error);
}
}
...
}
如果将用户分配到多个角色,则 roles 字符串会包含用逗号分隔的所有角色,例如 Orders.Manager,Store.Manager,...。 请确保你生成应用程序是为了处理以下情况:
- 令牌中缺少
roles声明 - 用户尚未分配到任何角色
- 在将用户分配到多个角色时,
roles声明中有多个值。
也可以检查群组声明值,如以下代码片段示例所示:
const tokenResponse = await msalInstance.acquireTokenByCode(authCodeRequest, req.body);
let groups = tokenResponse.idTokenClaims.groups;
组声明值是组的 objectId。 如果用户是多个组的成员,则 groups 字符串会包含用逗号分隔的所有组,例如 7f0621bc-b758-44fa-a2c6-...,6b35e65d-f3c8-4c6e-9538-...。
注释
如果向用户分配 Microsoft Entra 内置角色(通常也称为目录角色),这些角色会显示在安全令牌的组声明中。
处理组超额
为了确保安全令牌的大小不超过 HTTP 标头大小限制,外部 ID 会限制它在 组 声明中包含的对象 ID 数。 超额限制为 150(SAML 令牌)和 200(JWT 令牌)。 如果用户属于多个组,并且你请求了所有组,则可能会超出此限制。
在源代码中检测组超额
如果无法避免群组超量,则需要在代码中进行处理。 超出超额限制时,令牌不会包含组声明。 令牌会转而包含具有数组的组成员的 _claim_names 声明。 因此,你需要检查是否存在 _claim_names 声明,以确定是否出现了超额。 以下代码片段演示如何检测组超额:
const tokenResponse = await msalInstance.acquireTokenByCode(authCodeRequest, req.body);
if(tokenResponse.idTokenClaims.hasOwnProperty('_claim_names') && tokenResponse.idTokenClaims['_claim_names'].hasOwnProperty('groups')) {
//overage has occurred
}
遵循在令牌中配置组声明和应用角色一文中的说明,了解发生组超额时如何请求完整的组列表。
如何在 Node.js Web 应用中使用组和角色值
在客户端应用中,可以验证登录用户是否具有访问受保护路由或调用 API 终结点所需的角色。 要做到这一点,您需要检查 ID 令牌中的 roles 声明。 若要在应用中实现此防护,可以使用自定义中间件生成防护。
在服务应用(API 应用)中,还可以保护 API 终结点。 验证客户端应用发送的访问令牌后,可以在访问令牌的有效负载声明中检查角色或组声明。
我是使用应用角色还是组?
在本文中,你已了解可以使用应用角色或组来在应用程序中实现 RBAC。 首选方法是使用应用角色,因为它在应用程序级别管理访问/权限时提供更精细的控制。 有关如何选择方法的详细信息,请参阅选择方法。
后续步骤
- 详细了解在令牌中配置组声明和应用角色。