This is the platform-specific Accounts documentation for
@azure/msal-browser
. For the general documentation of theAccountInfo
object structure, please visit the@azure/msal-common
Accounts document. For documentation relating to multi-tenant accounts, please visit the Multi-tenant Accounts document.
The @azure/msal-browser
library provides the following APIs to access cached accounts:
getAllAccounts()
: returns all the accounts currently in the cache. Supports an optional filter to return a specific set of accounts. An application must choose an account to acquire tokens silently.getAccount()
: returns the first cached account that matches the filter passed in. The order in which accounts are read from the cache is arbitrary and there is no guarantee that the first account in the filtered list will be the same for any two calls ofgetAccount
. As explained below, increasing the number of filter attributes will provide more exact matches.
The AccountFilter type documentation lists the properties that can be used and combined to filter accounts.
Note: A single account filter attribute is usually not guaranteed to uniquely identify a cached account object. Adding a combination of attributes that don't repeat together, such as
homeAccountId
+localAccountId
, can help refine the search.
Note:
realm
istenantId
in the cache.
The following getAccountBy
APIs are marked for deprecation and will be removed in a future version of MSAL. Please migrate to getAccount()
:
getAccountByHomeId()
: receives ahomeAccountId
string and returns the matching account from the cache.getAccountByLocalId()
: receives alocalAccountId
string and returns the matching account from the cache.getAccountByUsername()
: receives ausername
string and returns the matching account from the cache.
The following is a usage examples that covers these APIs:
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
}
}
}
Now, account properties such as: homeAccountId
, localAccountId
, and username
can be used to look up the cached account before acquiring a token silently:
// 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);
});
}
As of @azure/msal-browser@3.2.0
, all login hint values can be used to search for and filter accounts. In order to filter by login hint, MSAL will compare the loginHint
value in the AccountFilter
object against the following account attributes (in order of precedence) to search for matches:
login_hint
ID token claim. Ignored in favor of the account attributes listed below whendomainHint
param is set as both opaquelogin_hint
anddomain_hint
can't be used togetherusername
account propertyupn
ID token claim
Note: All attributes above can be passed into the account filter as the
loginHint
property. The account filter will also accept theusername
attribute asusername
, and will yield a more performant search.
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);
});
Note: The
username
value can included in theAccountFilter
object as eitherusername
orloginHint
. This is because theusername
claim is one of the 3 values (along with thelogin_hint
andupn
ID token claims) that the token service accepts as login hint. If your application is certain that the value in question is ausername
, setting it as theAccountFilter.username
property will yield better search performance. Being able to set ausername
value asloginHint
is useful if your application utilizes a login hint and does not keep context on whether that value came from ausername
,login_hint
, orupn
claim.
Passing username
as 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);
});
Passing username
as 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);
});
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);
});
The @azure/msal-browser
library also provides 2 convenient APIs to help you keep track of which account is currently "active" and should be used for token requests.
getActiveAccount()
: Returns the current active accountsetActiveAccount()
: Receives an account object and sets it as the active account
Deciding which account to use to acquire tokens is app dependent, however, once you've determined which account you wish to use, simply call the setActiveAccount()
API with the chosen account object. Any acquireToken
, login
or ssoSilent
calls will now use the active account by default if a different account is not specified in the individual request. To clear the currently active account you can call 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"] });
}
Note: As of version 2.16.0 the active account is stored in the cache location configured on your PublicClientApplication
instance. If you are using a previous version the active account is stored in-memory and thus must be reset on every page load.
For NAA applications, we consider setActiveAccount()
and getActiveAccount()
as NO-OP APIs. Though we allow users to set and get active accounts, they are actively ignored since the NAA application is always expected to have one account and the account is supplied by the host application with accountContext
. In the future when multiple accounts are supported across the hubs, we expect this to change.
- The current msal-browser default sample has a working single account scenario.
- If you have a multiple accounts scenario, please modify the sample (in
handleResponse()
) to list all cached accounts and choose a specific account. - If an application wants to retrieve an account based on the
username
, it needs to save theusername
(from the response of alogin
API for a specific user) prior to usinggetAccountByUsername()
API. getAllAccounts()
will return multiple accounts if you have made several interactive token requests and the user has selected different accounts in two or more of those interactions. You may need to passprompt: "select_account"
orprompt: "login"
to the interactive acquireToken or login API in order for AAD to display the account selection screen after the first interaction.- The account APIs return local account state and do not necessarily reflect server state. They return accounts that have previously signed into this app using MSAL.js and the server session may or may not still be active.
- Two apps hosted on different domains do not share account state due to browser storage being segemented by domain.
getAllAccounts()
is not ordered and is not guaranteed to be in the same order across multiple calls- Each successful call to an acquireToken or login API will return exactly one account