semblance-dev/node_modules/@azure/msal-react/dist/hooks/useMsalAuthentication.js
2025-12-19 19:26:16 +00:00

197 lines
8.4 KiB
JavaScript
Executable file

/*! @azure/msal-react v3.0.17 2025-08-05 */
'use strict';
import { useState, useRef, useEffect, useCallback } from 'react';
import { InteractionStatus, InteractionType, EventType, InteractionRequiredAuthError, OIDC_DEFAULT_SCOPES } from '@azure/msal-browser';
import { useIsAuthenticated } from './useIsAuthenticated.js';
import { useMsal } from './useMsal.js';
import { useAccount } from './useAccount.js';
import { ReactAuthError } from '../error/ReactAuthError.js';
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
/**
* If a user is not currently signed in this hook invokes a login. Failed logins can be retried using the login callback returned.
* If a user is currently signed in this hook attempts to acquire a token. Subsequent token requests can use the acquireToken callback returned.
* Optionally provide a request object to be used in the login/acquireToken call.
* Optionally provide a specific user that should be logged in.
* @param interactionType
* @param authenticationRequest
* @param accountIdentifiers
*/
function useMsalAuthentication(interactionType, authenticationRequest, accountIdentifiers) {
const { instance, inProgress, logger } = useMsal();
const isAuthenticated = useIsAuthenticated(accountIdentifiers);
const account = useAccount(accountIdentifiers);
const [[result, error], setResponse] = useState([null, null]);
// Used to prevent state updates after unmount
const mounted = useRef(true);
useEffect(() => {
return () => {
mounted.current = false;
};
}, []);
// Boolean used to check if interaction is in progress in acquireTokenSilent fallback. Use Ref instead of state to prevent acquireToken function from being regenerated on each change to interactionInProgress value
const interactionInProgress = useRef(inProgress !== InteractionStatus.None);
useEffect(() => {
interactionInProgress.current = inProgress !== InteractionStatus.None;
}, [inProgress]);
// Flag used to control when the hook calls login/acquireToken
const shouldAcquireToken = useRef(true);
useEffect(() => {
if (!!error) {
// Errors should be handled by consuming component
shouldAcquireToken.current = false;
return;
}
if (!!result) {
// Token has already been acquired, consuming component/application is responsible for renewing
shouldAcquireToken.current = false;
return;
}
}, [error, result]);
const login = useCallback(async (callbackInteractionType, callbackRequest) => {
const loginType = callbackInteractionType || interactionType;
const loginRequest = callbackRequest || authenticationRequest;
switch (loginType) {
case InteractionType.Popup:
logger.verbose("useMsalAuthentication - Calling loginPopup");
return instance.loginPopup(loginRequest);
case InteractionType.Redirect:
// This promise is not expected to resolve due to full frame redirect
logger.verbose("useMsalAuthentication - Calling loginRedirect");
return instance
.loginRedirect(loginRequest)
.then(null);
case InteractionType.Silent:
logger.verbose("useMsalAuthentication - Calling ssoSilent");
return instance.ssoSilent(loginRequest);
default:
throw ReactAuthError.createInvalidInteractionTypeError();
}
}, [instance, interactionType, authenticationRequest, logger]);
const acquireToken = useCallback(async (callbackInteractionType, callbackRequest) => {
const fallbackInteractionType = callbackInteractionType || interactionType;
let tokenRequest;
if (callbackRequest) {
logger.trace("useMsalAuthentication - acquireToken - Using request provided in the callback");
tokenRequest = {
...callbackRequest,
};
}
else if (authenticationRequest) {
logger.trace("useMsalAuthentication - acquireToken - Using request provided in the hook");
tokenRequest = {
...authenticationRequest,
scopes: authenticationRequest.scopes || OIDC_DEFAULT_SCOPES,
};
}
else {
logger.trace("useMsalAuthentication - acquireToken - No request object provided, using default request.");
tokenRequest = {
scopes: OIDC_DEFAULT_SCOPES,
};
}
if (!tokenRequest.account && account) {
logger.trace("useMsalAuthentication - acquireToken - Attaching account to request");
tokenRequest.account = account;
}
const getToken = async () => {
logger.verbose("useMsalAuthentication - Calling acquireTokenSilent");
return instance
.acquireTokenSilent(tokenRequest)
.catch(async (e) => {
if (e instanceof InteractionRequiredAuthError) {
if (!interactionInProgress.current) {
logger.error("useMsalAuthentication - Interaction required, falling back to interaction");
return login(fallbackInteractionType, tokenRequest);
}
else {
logger.error("useMsalAuthentication - Interaction required but is already in progress. Please try again, if needed, after interaction completes.");
throw ReactAuthError.createUnableToFallbackToInteractionError();
}
}
throw e;
});
};
return getToken()
.then((response) => {
if (mounted.current) {
setResponse([response, null]);
}
return response;
})
.catch((e) => {
if (mounted.current) {
setResponse([null, e]);
}
throw e;
});
}, [
instance,
interactionType,
authenticationRequest,
logger,
account,
login,
]);
useEffect(() => {
const callbackId = instance.addEventCallback((message) => {
switch (message.eventType) {
case EventType.LOGIN_SUCCESS:
case EventType.SSO_SILENT_SUCCESS:
if (message.payload) {
setResponse([
message.payload,
null,
]);
}
break;
case EventType.LOGIN_FAILURE:
case EventType.SSO_SILENT_FAILURE:
if (message.error) {
setResponse([null, message.error]);
}
break;
}
});
logger.verbose(`useMsalAuthentication - Registered event callback with id: ${callbackId}`);
return () => {
if (callbackId) {
logger.verbose(`useMsalAuthentication - Removing event callback ${callbackId}`);
instance.removeEventCallback(callbackId);
}
};
}, [instance, logger]);
useEffect(() => {
if (shouldAcquireToken.current &&
inProgress === InteractionStatus.None) {
if (!isAuthenticated) {
shouldAcquireToken.current = false;
logger.info("useMsalAuthentication - No user is authenticated, attempting to login");
login().catch(() => {
// Errors are saved in state above
return;
});
}
else if (account) {
shouldAcquireToken.current = false;
logger.info("useMsalAuthentication - User is authenticated, attempting to acquire token");
acquireToken().catch(() => {
// Errors are saved in state above
return;
});
}
}
}, [isAuthenticated, account, inProgress, login, acquireToken, logger]);
return {
login,
acquireToken,
result,
error,
};
}
export { useMsalAuthentication };
//# sourceMappingURL=useMsalAuthentication.js.map