这是库的平台特定的帐户文档 @azure/msal-browser ,它提供以下 API 来访问缓存的帐户:
-
getAllAccounts():返回缓存中当前的所有帐户。 支持可选筛选器以返回一组特定的帐户。 应用程序必须选择帐户以无提示方式获取令牌。 -
getAccount():返回与传入的筛选器匹配的第一个缓存帐户。 从缓存中读取帐户的顺序是任意的,不能保证筛选列表中的第一个帐户对于任何两次getAccount调用都将相同。 如下所述,增加筛选器属性的数量将提供更精确的匹配项。
帐户筛选器对象
AccountFilter 类型文档列出了可用于筛选帐户和组合的属性。
注释
通常不能保证单个帐户筛选器属性能够唯一标识缓存的帐户对象。 添加不一起重复的属性的组合,例如 homeAccountId + localAccountId,可以帮助优化搜索。
注释
realm 位于 tenantId 缓存中。
已弃用以下 getAccountBy API。
getAccount()请改用适当的筛选器对象:
-
getAccountByHomeId():请改用getAccount({ homeAccountId })。 -
getAccountByLocalId():请改用getAccount({ localAccountId })。 -
getAccountByUsername():请改用getAccount({ username })。
下面是涵盖这些 API 的用法示例:
let homeAccountId = null; // Initialize global accountId (can also be localAccountId or username) used for account lookup later, ideally stored in app state
// This callback is passed into `acquireTokenPopup` and `acquireTokenRedirect` to handle the interactive auth response
function handleResponse(resp) {
if (resp !== null) {
homeAccountId = resp.account.homeAccountId; // alternatively: resp.account.homeAccountId or resp.account.username
} else {
const currentAccounts = myMSALObj.getAllAccounts();
if (currentAccounts.length < 1) { // No cached accounts
return;
} else if (currentAccounts.length > 1) { // Multiple account scenario
// Add account selection code here
homeAccountId = ...
} else if (currentAccounts.length === 1) {
homeAccountId = currentAccounts[0].homeAccountId; // Single account scenario
}
}
}
现在,帐户属性(例如: homeAccountId) localAccountId可用于 username 在以无提示方式获取令牌之前查找缓存的帐户:
// This method attempts silent token acquisition and falls back on acquireTokenPopup
async function getTokenPopup(request, homeAccountId) {
// In this case, accounts are filtered by homeAccountId, but more attributes can be added to refine the search and increase the precision of the account filter
const accountFilter = {
homeAccountId: homeAccountId,
};
request.account = myMSALObj.getAccount(accountFilter);
return await myMSALObj.acquireTokenSilent(request).catch(async (error) => {
// Handle error
return await myMSALObj.acquireTokenPopup(request);
});
}
按登录提示进行筛选
因此 @azure/[email protected],所有登录提示值都可用于搜索和筛选帐户。 为了按登录提示进行筛选,MSAL 会将对象中的AccountFilter值与以下帐户属性(优先顺序)进行比较loginHint,以搜索匹配项:
-
login_hintID 令牌声明 -
usernameaccount 属性 -
upnID 令牌声明
注释
上述所有属性都可以作为属性传递到帐户筛选器 loginHint 中。 帐户筛选器也将接受该 username 属性, username并且将产生更高性能的搜索。
使用 login_hint 声明
const accountFilter = {
loginHint: previouslyObtainedIdTokenClaims.login_hint;
};
request.account = myMSALObj.getAccount(accountFilter);
return await myMSALObj.acquireTokenSilent(request).catch(async (error) => {
// Handle error
return await myMSALObj.acquireTokenPopup(request);
});
使用“username”
注释
值 username 可以作为 AccountFilter 或 usernameloginHint. 这是因为username声明是令牌服务作为登录提示接受的 3 个值之一(以及 upnlogin_hint ID 令牌声明)。 如果应用程序确定有问题的值为, username则将其设置为 AccountFilter.username 属性将产生更好的搜索性能。 如果应用程序使用登录提示,并且不保留该值来自某个username或login_hintupn声明的上下文,则能够将值loginHint设置为username有用。
传递 username 为 loginHint
const accountUsername = userProfile.username;
const accountFilter = {
loginHint: accountUsername;
};
request.account = myMSALObj.getAccount(accountFilter);
return await myMSALObj.acquireTokenSilent(request).catch(async (error) => {
// Handle error
return await myMSALObj.acquireTokenPopup(request);
});
传递 username 为 username
const accountUsername = userProfile.username;
const accountFilter = {
username: accountUsername;
};
request.account = myMSALObj.getAccount(accountFilter);
return await myMSALObj.acquireTokenSilent(request).catch(async (error) => {
// Handle error
return await myMSALObj.acquireTokenPopup(request);
});
使用 upn 声明
const accountFilter = {
loginHint: previouslyObtainedIdTokenClaims.upn;
};
request.account = myMSALObj.getAccount(accountFilter);
return await myMSALObj.acquireTokenSilent(request).catch(async (error) => {
// Handle error
return await myMSALObj.acquireTokenPopup(request);
});
活动帐户 API
该 @azure/msal-browser 库还提供了 2 个方便的 API,可帮助你跟踪当前“活动”的帐户,并应用于令牌请求。
-
getActiveAccount():返回当前活动帐户 -
setActiveAccount():接收帐户对象并将其设置为活动帐户
但是,确定要用于获取令牌的帐户取决于应用,但确定要使用的帐户后,只需使用所选帐户对象调用 setActiveAccount() API。 如果acquireToken单个请求中未指定其他帐户,则ssoSilent任何调用login现在都将使用活动帐户。 若要清除当前处于活动状态的帐户,可以调用 setActiveAccount(null)。
function login() {
return myMsalObj.loginPopup().then((response) => {
// After a successful login set the active account to be the user that just logged in
myMsalObj.setActiveAccount(response.account);
});
}
function getAccessToken() {
// Providing an account in the token request is not required if there is an active account set
return myMsalObj.acquireTokenSilent({ scopes: ["User.Read"] });
}
注意:从版本 2.16.0 起,活动帐户存储在实例上 PublicClientApplication 配置的缓存位置。 如果使用以前的版本,活动帐户将存储在内存中,因此必须在每次页面加载时重置。
嵌套应用身份验证
对于 NAA 应用程序, setActiveAccount() NO-OP getActiveAccount() API。 尽管用户可以设置和获取活动帐户,但它们会被主动忽略,因为 NAA 应用程序始终应有 一个 帐户,并且该帐户由主机应用程序提供 accountContext。 将来,当跨中心支持多个帐户时,此行为预计将发生更改。
备注
- 当前的 msal-browser 默认 示例 具有一个工作单帐户方案。
- 如果你有多个帐户方案,请修改 示例 (in
handleResponse())以列出所有缓存帐户并选择特定的帐户。 - 如果应用程序希望基于帐户
username检索帐户,则需要在 API 中使用username筛选器之前保存username(从特定用户的 API 响应login中getAccount())。 -
getAllAccounts()如果已发出多个交互式令牌请求,并且用户在两个或多个交互中选择了不同的帐户,将返回多个帐户。 可能需要传递或prompt: "login"传递给prompt: "select_account"交互式 acquireToken 或登录 API,以便Microsoft Entra ID在第一次交互后显示帐户选择屏幕。 - 帐户 API 返回本地帐户状态,不一定反映服务器状态。 它们返回以前使用 MSAL.js 登录到此应用的帐户,并且服务器会话可能仍然处于活动状态或可能仍然处于活动状态。
- 由于浏览器存储被域分列,托管在不同域上的两个应用不会共享帐户状态。
-
getAllAccounts()未排序,不能保证跨多个调用的顺序相同 - 每次成功调用 acquireToken 或登录 API 将只返回一个帐户