Msal-Browser (@azure/msal-browser
) starting at version 2.4 now provides event APIs that are available to users of our core library and wrapper libraries. These events are related to auth and what MSAL is doing, and can be used in applications to update UI, show error messages, and so on.
export type EventMessage = {
eventType: EventType;
interactionType: InteractionType | null;
payload: EventPayload;
error: EventError;
timestamp: number;
};
You can consult the EventPayload and EventError type docs to understand how they are defined in MSAL.
Msal-browser has a protected function emitEvent
, and emits events in major APIs. For the list of currently emitted events, see the table below.
Here is an example of how msal-browser emits an event with a payload, or with an error:
this.emitEvent(EventType.LOGIN_SUCCESS, InteractionType.Redirect, result);
this.emitEvent(EventType.LOGIN_FAILURE, InteractionType.Redirect, null, e);
Msal-browser exports the addEventCallback
function which takes in a callback function and can be used to process emitted events.
Here is an example of how you could consume the emitted events in your application:
const callbackId = msalInstance.addEventCallback((message: EventMessage) => {
// Update UI or interact with EventMessage here
if (message.eventType === EventType.LOGIN_SUCCESS) {
console.log(message.payload);
}
});
Adding an event callback will return an id. This id can be used to remove the callback if necessary, using the removeEventCallback
function exported by msal-browser:
msalInstance.removeEventCallback(callbackId);
Due to the way EventError
is defined, handling errors emitted with an event may require validating that the error is of the correct type before accessing specific properties on the emitted error. The error can be cast to AuthError
or checked that it is an instance of AuthError
.
Here is an example of consuming an emitted event and casting the error:
const callbackId = msalInstance.addEventCallback((message: EventMessage) => {
// Update UI or interact with EventMessage here
if (message.eventType === EventType.LOGIN_FAILURE) {
if (message.error instanceof AuthError) {
// Do something with the error
}
}
});
You can get the current interaction status from events by using the getInteractionStatusFromEvent API:
Here is an example of displaying a message when there are no interactions in progress:
const callbackId = msalInstance.addEventCallback((message: EventMessage) => {
const status = EventMessageUtils.getInteractionStatusFromEvent(message);
// Update UI or interact with EventMessage here
if (status === InteractionStatus.None) {
console.log(message.payload);
}
});
If you would like to update your UI when a user logs in or out of your app or changes the active account in a different tab or window you can subscribe to the ACCOUNT_ADDED
, ACCOUNT_REMOVED
, and ACTIVE_ACCOUNT_CHANGED
events.
- For account additions and removals, the payload will be the
AccountInfo
object that was added or removed. - For active account updates, there will be no payload
These events will not be emitted by default. In order to enable these events you must call the enableAccountStorageEvents
API before registering your event callbacks:
msalInstance.enableAccountStorageEvents();
msalInstance.addEventCallback((message: EventMessage) => {
if (message.eventType === EventType.ACCOUNT_ADDED) {
// Update UI with new account
} else if (message.eventType === EventType.ACCOUNT_REMOVED) {
// Update UI with account logged out
} else if (message.eventType === EventType.ACTIVE_ACCOUNT_CHANGED) {
const accountInfo = msalInstance.getActiveAccount();
// Update UI with new active account info
}
});
You can also disable these events if no longer needed by calling disableAccountStorageEvents
:
msalInstance.disableAccountStorageEvents();
These are the events currently emitted by msal-browser.
Event Type | Description | Interaction Type | Payload | Error |
---|---|---|---|---|
LOGIN_START |
LoginPopup or loginRedirect is called | Popup or Redirect |
PopupRequest or RedirectRequest | |
LOGIN_SUCCESS |
Successfully logged in | Popup or Redirect |
AuthenticationResult | |
LOGIN_FAILURE |
Error when logging in | Popup or Redirect |
AuthError or Error | |
ACQUIRE_TOKEN_START |
AcquireTokenPopup or acquireTokenRedirect or acquireTokenSilent is called | Popup or Redirect or Silent |
PopupRequest or RedirectRequest or SilentRequest | |
ACQUIRE_TOKEN_SUCCESS |
Successfully acquired token from cache or network | Popup or Redirect or Silent |
AuthenticationResult | |
ACQUIRE_TOKEN_FAILURE |
Error when acquiring token | Popup or Redirect or Silent |
AuthError or Error | |
ACQUIRE_TOKEN_NETWORK_START |
Starting acquiring token from network | Silent |
||
SSO_SILENT_START |
SsoSilent API called | Silent |
SsoSilentRequest | |
SSO_SILENT_SUCCESS |
SsoSilent succeeded | Silent |
AuthenticationResult | |
SSO_SILENT_FAILURE |
SsoSilent failed | Silent |
AuthError or Error | |
HANDLE_REDIRECT_START |
HandleRedirectPromise called | Redirect |
||
HANDLE_REDIRECT_END |
HandleRedirectPromise finished | Redirect |
||
LOGOUT_START |
Logout called | Redirect or Popup |
EndSessionRequest or EndSessionPopupRequest | |
LOGOUT_END |
Logout finished | Redirect or Popup |
||
LOGOUT_SUCCESS |
Logout success | Redirect or Popup |
EndSessionRequest or EndSessionPopupRequest | |
LOGOUT_FAILURE |
Logout failed | Redirect or Popup |
AuthError or Error | |
ACCOUNT_ADDED |
Account logged-in in a different tab or window | N/A | AccountInfo | N/A |
ACCOUNT_REMOVED |
Account logged-out in a different tab or window | N/A | AccountInfo | N/A |
ACTIVE_ACCOUNT_CHANGED |
Active account filters where changed in a different tab or window | N/A | N/A | NA |
INITIALIZE_START |
Initialize function called | N/A | N/A | N/A |
INITIALIZE_END |
Initialize function completed | N/A | N/A | N/A |