Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@azure/msal-react

Package Overview
Dependencies
Maintainers
3
Versions
82
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@azure/msal-react - npm Package Compare versions

Comparing version 1.2.0 to 1.3.0

dist/error/ReactAuthError.d.ts

35

CHANGELOG.json

@@ -5,2 +5,37 @@ {

{
"date": "Tue, 08 Feb 2022 00:41:07 GMT",
"tag": "@azure/msal-react_v1.3.0",
"version": "1.3.0",
"comments": {
"minor": [
{
"author": "thomas.norling@microsoft.com",
"package": "@azure/msal-react",
"commit": "67ce881faa2a6931320541d99de2efe4e9ba6a3f",
"comment": "useMsalAuthentication hook acquires a token if user is already signed in #4280"
},
{
"author": "beachball",
"package": "@azure/msal-react",
"comment": "Bump @azure/msal-browser to v2.22.0",
"commit": "639253acbc825e1f19ca712bc72dce8da149e3e8"
}
],
"none": [
{
"author": "kamausamuel11@gmail.com",
"package": "@azure/msal-react",
"commit": "5767008f8ef9f3b05aeba421cc4aa6c6bb616e86",
"comment": "fix: update package-lock files"
},
{
"author": "thomas.norling@microsoft.com",
"package": "@azure/msal-react",
"commit": "19f76b1d9cd2b0f1a4a7e4765c8ee9e7e17f3d59",
"comment": "Test changes #4383"
}
]
}
},
{
"date": "Tue, 04 Jan 2022 00:20:29 GMT",

@@ -7,0 +42,0 @@ "tag": "@azure/msal-react_v1.2.0",

11

CHANGELOG.md
# Change Log - @azure/msal-react
This log was last generated on Tue, 04 Jan 2022 00:20:29 GMT and should not be manually modified.
This log was last generated on Tue, 08 Feb 2022 00:41:07 GMT and should not be manually modified.
<!-- Start content -->
## 1.3.0
Tue, 08 Feb 2022 00:41:07 GMT
### Minor changes
- useMsalAuthentication hook acquires a token if user is already signed in #4280 (thomas.norling@microsoft.com)
- Bump @azure/msal-browser to v2.22.0
## 1.2.0

@@ -8,0 +17,0 @@

2

dist/hooks/useAccount.d.ts

@@ -7,2 +7,2 @@ import { AccountInfo } from "@azure/msal-browser";

*/
export declare function useAccount(accountIdentifiers: AccountIdentifiers): AccountInfo | null;
export declare function useAccount(accountIdentifiers?: AccountIdentifiers): AccountInfo | null;

@@ -1,5 +0,6 @@

import { PopupRequest, RedirectRequest, SsoSilentRequest, InteractionType, AuthenticationResult, AuthError } from "@azure/msal-browser";
import { PopupRequest, RedirectRequest, SsoSilentRequest, InteractionType, AuthenticationResult, AuthError, SilentRequest } from "@azure/msal-browser";
import { AccountIdentifiers } from "../types/AccountIdentifiers";
export declare type MsalAuthenticationResult = {
login: Function;
login: (callbackInteractionType?: InteractionType | undefined, callbackRequest?: PopupRequest | RedirectRequest | SilentRequest) => Promise<AuthenticationResult | null>;
acquireToken: (callbackInteractionType?: InteractionType | undefined, callbackRequest?: SilentRequest | undefined) => Promise<AuthenticationResult | null>;
result: AuthenticationResult | null;

@@ -9,4 +10,5 @@ error: AuthError | null;

/**
* Invokes a login call if a user is not currently signed-in. Failed logins can be retried using the login callback returned.
* Optionally provide a request object to be used in the login call.
* 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.

@@ -13,0 +15,0 @@ * @param interactionType

@@ -63,6 +63,28 @@ 'use strict';

}
function getAccountByIdentifiers(allAccounts, accountIdentifiers) {
if (allAccounts.length > 0 && (accountIdentifiers.homeAccountId || accountIdentifiers.localAccountId || accountIdentifiers.username)) {
const matchedAccounts = allAccounts.filter(accountObj => {
if (accountIdentifiers.username && accountIdentifiers.username.toLowerCase() !== accountObj.username.toLowerCase()) {
return false;
}
if (accountIdentifiers.homeAccountId && accountIdentifiers.homeAccountId.toLowerCase() !== accountObj.homeAccountId.toLowerCase()) {
return false;
}
if (accountIdentifiers.localAccountId && accountIdentifiers.localAccountId.toLowerCase() !== accountObj.localAccountId.toLowerCase()) {
return false;
}
return true;
});
return matchedAccounts[0] || null;
} else {
return null;
}
}
/* eslint-disable header/header */
const name = "@azure/msal-react";
const version = "1.2.0";
const version = "1.3.0";

@@ -85,3 +107,3 @@ /*

const [accounts, setAccounts] = React.useState([]); // State hook to store in progress value
const [accounts, setAccounts] = React.useState(() => instance.getAllAccounts()); // State hook to store in progress value

@@ -182,57 +204,5 @@ const [inProgress, setInProgress] = React.useState(msalBrowser.InteractionStatus.Startup); // Mutable object used in the event callback

function getAccount(instance, accountIdentifiers) {
const allAccounts = instance.getAllAccounts();
if (allAccounts.length > 0 && (accountIdentifiers.homeAccountId || accountIdentifiers.localAccountId || accountIdentifiers.username)) {
const matchedAccounts = allAccounts.filter(accountObj => {
if (accountIdentifiers.username && accountIdentifiers.username.toLowerCase() !== accountObj.username.toLowerCase()) {
return false;
}
if (accountIdentifiers.homeAccountId && accountIdentifiers.homeAccountId.toLowerCase() !== accountObj.homeAccountId.toLowerCase()) {
return false;
}
if (accountIdentifiers.localAccountId && accountIdentifiers.localAccountId.toLowerCase() !== accountObj.localAccountId.toLowerCase()) {
return false;
}
return true;
});
return matchedAccounts[0] || null;
} else {
return null;
}
}
/**
* Given 1 or more accountIdentifiers, returns the Account object if the user is signed-in
* @param accountIdentifiers
*/
function useAccount(accountIdentifiers) {
const {
instance,
inProgress
} = useMsal();
const initialStateValue = inProgress === msalBrowser.InteractionStatus.Startup ? null : getAccount(instance, accountIdentifiers);
const [account, setAccount] = React.useState(initialStateValue);
React.useEffect(() => {
const currentAccount = getAccount(instance, accountIdentifiers);
if (!msalBrowser.AccountEntity.accountInfoIsEqual(account, currentAccount, true)) {
setAccount(currentAccount);
}
}, [inProgress, accountIdentifiers, instance, account]);
return account;
}
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
function isAuthenticated(allAccounts, account, matchAccount) {
function isAuthenticated(allAccounts, matchAccount) {
if (matchAccount && (matchAccount.username || matchAccount.homeAccountId || matchAccount.localAccountId)) {
return !!account;
return !!getAccountByIdentifiers(allAccounts, matchAccount);
}

@@ -250,11 +220,8 @@

const {
accounts: allAccounts,
inProgress
accounts: allAccounts
} = useMsal();
const account = useAccount(matchAccount || {});
const initialStateValue = inProgress === msalBrowser.InteractionStatus.Startup ? false : isAuthenticated(allAccounts, account, matchAccount);
const [hasAuthenticated, setHasAuthenticated] = React.useState(initialStateValue);
const [hasAuthenticated, setHasAuthenticated] = React.useState(() => isAuthenticated(allAccounts, matchAccount));
React.useEffect(() => {
setHasAuthenticated(isAuthenticated(allAccounts, account, matchAccount));
}, [allAccounts, account, matchAccount]);
setHasAuthenticated(isAuthenticated(allAccounts, matchAccount));
}, [allAccounts, matchAccount]);
return hasAuthenticated;

@@ -331,5 +298,78 @@ }

*/
function getAccount(instance, accountIdentifiers) {
if (!accountIdentifiers || !accountIdentifiers.homeAccountId && !accountIdentifiers.localAccountId && !accountIdentifiers.username) {
// If no account identifiers are provided, return active account
return instance.getActiveAccount();
}
return getAccountByIdentifiers(instance.getAllAccounts(), accountIdentifiers);
}
/**
* Invokes a login call if a user is not currently signed-in. Failed logins can be retried using the login callback returned.
* Optionally provide a request object to be used in the login call.
* Given 1 or more accountIdentifiers, returns the Account object if the user is signed-in
* @param accountIdentifiers
*/
function useAccount(accountIdentifiers) {
const {
instance,
inProgress,
logger
} = useMsal();
const [account, setAccount] = React.useState(() => getAccount(instance, accountIdentifiers));
React.useEffect(() => {
setAccount(currentAccount => {
const nextAccount = getAccount(instance, accountIdentifiers);
if (!msalBrowser.AccountEntity.accountInfoIsEqual(currentAccount, nextAccount, true)) {
logger.info("useAccount - Updating account");
return nextAccount;
}
return currentAccount;
});
}, [inProgress, accountIdentifiers, instance, logger]);
return account;
}
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
const ReactAuthErrorMessage = {
invalidInteractionType: {
code: "invalid_interaction_type",
desc: "The provided interaction type is invalid."
},
unableToFallbackToInteraction: {
code: "unable_to_fallback_to_interaction",
desc: "Interaction is required but another interaction is already in progress. Please try again when the current interaction is complete."
}
};
class ReactAuthError extends msalBrowser.AuthError {
constructor(errorCode, errorMessage) {
super(errorCode, errorMessage);
Object.setPrototypeOf(this, ReactAuthError.prototype);
this.name = "ReactAuthError";
}
static createInvalidInteractionTypeError() {
return new ReactAuthError(ReactAuthErrorMessage.invalidInteractionType.code, ReactAuthErrorMessage.invalidInteractionType.desc);
}
static createUnableToFallbackToInteractionError() {
return new ReactAuthError(ReactAuthErrorMessage.unableToFallbackToInteraction.code, ReactAuthErrorMessage.unableToFallbackToInteraction.desc);
}
}
/*
* 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.

@@ -348,4 +388,24 @@ * @param interactionType

const isAuthenticated = useIsAuthenticated(accountIdentifiers);
const [[result, error], setResponse] = React.useState([null, null]);
const [hasBeenCalled, setHasBeenCalled] = React.useState(false);
const account = useAccount(accountIdentifiers);
const [[result, error], setResponse] = React.useState([null, null]); // 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 = React.useRef(inProgress !== msalBrowser.InteractionStatus.None);
React.useEffect(() => {
interactionInProgress.current = inProgress !== msalBrowser.InteractionStatus.None;
}, [inProgress]); // Flag used to control when the hook calls login/acquireToken
const shouldAcquireToken = React.useRef(true);
React.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 = React.useCallback(async (callbackInteractionType, callbackRequest) => {

@@ -370,5 +430,55 @@ const loginType = callbackInteractionType || interactionType;

default:
throw "Invalid interaction type provided.";
throw ReactAuthError.createInvalidInteractionTypeError();
}
}, [instance, interactionType, authenticationRequest, logger]);
const acquireToken = React.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 || msalBrowser.OIDC_DEFAULT_SCOPES
};
} else {
logger.trace("useMsalAuthentication - acquireToken - No request object provided, using default request.");
tokenRequest = {
scopes: msalBrowser.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 msalBrowser.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 => {
setResponse([response, null]);
return response;
}).catch(e => {
setResponse([null, e]);
throw e;
});
}, [instance, interactionType, authenticationRequest, logger, account, login]);
React.useEffect(() => {

@@ -403,14 +513,23 @@ const callbackId = instance.addEventCallback(message => {

React.useEffect(() => {
if (!hasBeenCalled && !error && !isAuthenticated && inProgress === msalBrowser.InteractionStatus.None) {
logger.info("useMsalAuthentication - No user is authenticated, attempting to login"); // Ensure login is only called one time from within this hook, any subsequent login attempts should use the callback returned
if (shouldAcquireToken.current && inProgress === msalBrowser.InteractionStatus.None) {
shouldAcquireToken.current = false;
setHasBeenCalled(true);
login().catch(() => {
// Errors are handled by the event handler above
return;
});
if (!isAuthenticated) {
logger.info("useMsalAuthentication - No user is authenticated, attempting to login");
login().catch(() => {
// Errors are saved in state above
return;
});
} else if (account) {
logger.info("useMsalAuthentication - User is authenticated, attempting to acquire token");
acquireToken().catch(() => {
// Errors are saved in state above
return;
});
}
}
}, [isAuthenticated, inProgress, error, hasBeenCalled, login, logger]);
}, [isAuthenticated, account, inProgress, login, acquireToken, logger]);
return {
login,
acquireToken,
result,

@@ -417,0 +536,0 @@ error

@@ -1,2 +0,2 @@

"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=require("react"),n=(e=t)&&"object"==typeof e&&"default"in e?e.default:e,o=require("@azure/msal-browser");const r=t.createContext({instance:o.stubbedPublicClientApplication,inProgress:o.InteractionStatus.None,accounts:[],logger:new o.Logger({})}),c=r.Consumer;function a(e,t){return"function"==typeof e?e(t):e}const s=()=>t.useContext(r);function u(e,t){const n=e.getAllAccounts();return n.length>0&&(t.homeAccountId||t.localAccountId||t.username)&&n.filter(e=>!(t.username&&t.username.toLowerCase()!==e.username.toLowerCase()||t.homeAccountId&&t.homeAccountId.toLowerCase()!==e.homeAccountId.toLowerCase()||t.localAccountId&&t.localAccountId.toLowerCase()!==e.localAccountId.toLowerCase()))[0]||null}function l(e){const{instance:n,inProgress:r}=s(),c=r===o.InteractionStatus.Startup?null:u(n,e),[a,l]=t.useState(c);return t.useEffect(()=>{const t=u(n,e);o.AccountEntity.accountInfoIsEqual(a,t,!0)||l(t)},[r,e,n,a]),a}function i(e,t,n){return n&&(n.username||n.homeAccountId||n.localAccountId)?!!t:e.length>0}function d(e){const{accounts:n,inProgress:r}=s(),c=l(e||{}),a=r!==o.InteractionStatus.Startup&&i(n,c,e),[u,d]=t.useState(a);return t.useEffect(()=>{d(i(n,c,e))},[n,c,e]),u}function p(e,n,r){const{instance:c,inProgress:a,logger:u}=s(),l=d(r),[[i,p],m]=t.useState([null,null]),[E,I]=t.useState(!1),v=t.useCallback(async(t,r)=>{const a=r||n;switch(t||e){case o.InteractionType.Popup:return u.verbose("useMsalAuthentication - Calling loginPopup"),c.loginPopup(a);case o.InteractionType.Redirect:return u.verbose("useMsalAuthentication - Calling loginRedirect"),c.loginRedirect(a).then(null);case o.InteractionType.Silent:return u.verbose("useMsalAuthentication - Calling ssoSilent"),c.ssoSilent(a);default:throw"Invalid interaction type provided."}},[c,e,n,u]);return t.useEffect(()=>{const e=c.addEventCallback(e=>{switch(e.eventType){case o.EventType.LOGIN_SUCCESS:case o.EventType.SSO_SILENT_SUCCESS:e.payload&&m([e.payload,null]);break;case o.EventType.LOGIN_FAILURE:case o.EventType.SSO_SILENT_FAILURE:e.error&&m([null,e.error])}});return u.verbose("useMsalAuthentication - Registered event callback with id: "+e),()=>{e&&(u.verbose("useMsalAuthentication - Removing event callback "+e),c.removeEventCallback(e))}},[c,u]),t.useEffect(()=>{E||p||l||a!==o.InteractionStatus.None||(u.info("useMsalAuthentication - No user is authenticated, attempting to login"),I(!0),v().catch(()=>{}))},[l,a,p,E,v,u]),{login:v,result:i,error:p}}exports.AuthenticatedTemplate=function({username:e,homeAccountId:r,localAccountId:c,children:u}){const l=s();return d(t.useMemo(()=>({username:e,homeAccountId:r,localAccountId:c}),[e,r,c]))&&l.inProgress!==o.InteractionStatus.Startup?n.createElement(n.Fragment,null,a(u,l)):null},exports.MsalAuthenticationTemplate=function({interactionType:e,username:r,homeAccountId:c,localAccountId:u,authenticationRequest:l,loadingComponent:i,errorComponent:m,children:E}){const I=t.useMemo(()=>({username:r,homeAccountId:c,localAccountId:u}),[r,c,u]),v=s(),S=p(e,l,I),g=d(I);if(S.error&&v.inProgress===o.InteractionStatus.None){if(m)return n.createElement(m,Object.assign({},S));throw S.error}return g?n.createElement(n.Fragment,null,a(E,S)):i&&v.inProgress!==o.InteractionStatus.None?n.createElement(i,Object.assign({},v)):null},exports.MsalConsumer=c,exports.MsalContext=r,exports.MsalProvider=function({instance:e,children:c}){t.useEffect(()=>{e.initializeWrapperLibrary(o.WrapperSKU.React,"1.2.0")},[e]);const a=t.useMemo(()=>e.getLogger().clone("@azure/msal-react","1.2.0"),[e]),[s,u]=t.useState([]),[l,i]=t.useState(o.InteractionStatus.Startup),d=t.useRef(l);return t.useEffect(()=>{const t=e.addEventCallback(t=>{switch(t.eventType){case o.EventType.ACCOUNT_ADDED:case o.EventType.ACCOUNT_REMOVED:case o.EventType.LOGIN_SUCCESS:case o.EventType.SSO_SILENT_SUCCESS:case o.EventType.HANDLE_REDIRECT_END:case o.EventType.LOGIN_FAILURE:case o.EventType.SSO_SILENT_FAILURE:case o.EventType.LOGOUT_END:case o.EventType.ACQUIRE_TOKEN_SUCCESS:case o.EventType.ACQUIRE_TOKEN_FAILURE:const t=e.getAllAccounts();!function(e,t){if(e.length!==t.length)return!1;const n=[...t];return e.every(e=>{const t=n.shift();return!(!e||!t)&&e.homeAccountId===t.homeAccountId&&e.localAccountId===t.localAccountId&&e.username===t.username})}(t,s)?(a.info("MsalProvider - updating account state"),u(t)):a.info("MsalProvider - no account changes")}});return a.verbose("MsalProvider - Registered event callback with id: "+t),()=>{t&&(a.verbose("MsalProvider - Removing event callback "+t),e.removeEventCallback(t))}},[e,s,a]),t.useEffect(()=>{const t=e.addEventCallback(e=>{const t=o.EventMessageUtils.getInteractionStatusFromEvent(e,d.current);null!==t&&(a.info(`MsalProvider - ${e.eventType} results in setting inProgress from ${d.current} to ${t}`),d.current=t,i(t))});return a.verbose("MsalProvider - Registered event callback with id: "+t),e.handleRedirectPromise().catch(()=>{}).finally(()=>{d.current===o.InteractionStatus.Startup&&(d.current=o.InteractionStatus.None,i(o.InteractionStatus.None))}),()=>{t&&(a.verbose("MsalProvider - Removing event callback "+t),e.removeEventCallback(t))}},[e,a]),n.createElement(r.Provider,{value:{instance:e,inProgress:l,accounts:s,logger:a}},c)},exports.UnauthenticatedTemplate=function({username:e,homeAccountId:r,localAccountId:c,children:u}){const l=s();return d(t.useMemo(()=>({username:e,homeAccountId:r,localAccountId:c}),[e,r,c]))||l.inProgress===o.InteractionStatus.Startup||l.inProgress===o.InteractionStatus.HandleRedirect?null:n.createElement(n.Fragment,null,a(u,l))},exports.useAccount=l,exports.useIsAuthenticated=d,exports.useMsal=s,exports.useMsalAuthentication=p,exports.version="1.2.0",exports.withMsal=e=>{const t=t=>{const o=s();return n.createElement(e,Object.assign({},t,{msalContext:o}))};return t.displayName=`withMsal(${e.displayName||e.name||"Component"})`,t};
"use strict";Object.defineProperty(exports,"__esModule",{value:!0});var e,t=require("react"),n=(e=t)&&"object"==typeof e&&"default"in e?e.default:e,r=require("@azure/msal-browser");const o=t.createContext({instance:r.stubbedPublicClientApplication,inProgress:r.InteractionStatus.None,accounts:[],logger:new r.Logger({})}),c=o.Consumer;function a(e,t){return"function"==typeof e?e(t):e}function s(e,t){return e.length>0&&(t.homeAccountId||t.localAccountId||t.username)&&e.filter(e=>!(t.username&&t.username.toLowerCase()!==e.username.toLowerCase()||t.homeAccountId&&t.homeAccountId.toLowerCase()!==e.homeAccountId.toLowerCase()||t.localAccountId&&t.localAccountId.toLowerCase()!==e.localAccountId.toLowerCase()))[0]||null}const u=()=>t.useContext(o);function i(e,t){return t&&(t.username||t.homeAccountId||t.localAccountId)?!!s(e,t):e.length>0}function l(e){const{accounts:n}=u(),[r,o]=t.useState(()=>i(n,e));return t.useEffect(()=>{o(i(n,e))},[n,e]),r}function d(e,t){return t&&(t.homeAccountId||t.localAccountId||t.username)?s(e.getAllAccounts(),t):e.getActiveAccount()}function p(e){const{instance:n,inProgress:o,logger:c}=u(),[a,s]=t.useState(()=>d(n,e));return t.useEffect(()=>{s(t=>{const o=d(n,e);return r.AccountEntity.accountInfoIsEqual(t,o,!0)?t:(c.info("useAccount - Updating account"),o)})},[o,e,n,c]),a}class h extends r.AuthError{constructor(e,t){super(e,t),Object.setPrototypeOf(this,h.prototype),this.name="ReactAuthError"}static createInvalidInteractionTypeError(){return new h("invalid_interaction_type","The provided interaction type is invalid.")}static createUnableToFallbackToInteractionError(){return new h("unable_to_fallback_to_interaction","Interaction is required but another interaction is already in progress. Please try again when the current interaction is complete.")}}function E(e,n,o){const{instance:c,inProgress:a,logger:s}=u(),i=l(o),d=p(o),[[E,I],A]=t.useState([null,null]),g=t.useRef(a!==r.InteractionStatus.None);t.useEffect(()=>{g.current=a!==r.InteractionStatus.None},[a]);const m=t.useRef(!0);t.useEffect(()=>{(I||E)&&(m.current=!1)},[I,E]);const v=t.useCallback(async(t,o)=>{const a=o||n;switch(t||e){case r.InteractionType.Popup:return s.verbose("useMsalAuthentication - Calling loginPopup"),c.loginPopup(a);case r.InteractionType.Redirect:return s.verbose("useMsalAuthentication - Calling loginRedirect"),c.loginRedirect(a).then(null);case r.InteractionType.Silent:return s.verbose("useMsalAuthentication - Calling ssoSilent"),c.ssoSilent(a);default:throw h.createInvalidInteractionTypeError()}},[c,e,n,s]),f=t.useCallback(async(t,o)=>{const a=t||e;let u;return o?(s.trace("useMsalAuthentication - acquireToken - Using request provided in the callback"),u={...o}):n?(s.trace("useMsalAuthentication - acquireToken - Using request provided in the hook"),u={...n,scopes:n.scopes||r.OIDC_DEFAULT_SCOPES}):(s.trace("useMsalAuthentication - acquireToken - No request object provided, using default request."),u={scopes:r.OIDC_DEFAULT_SCOPES}),!u.account&&d&&(s.trace("useMsalAuthentication - acquireToken - Attaching account to request"),u.account=d),(async()=>(s.verbose("useMsalAuthentication - Calling acquireTokenSilent"),c.acquireTokenSilent(u).catch(async e=>{if(e instanceof r.InteractionRequiredAuthError){if(g.current)throw s.error("useMsalAuthentication - Interaction required but is already in progress. Please try again, if needed, after interaction completes."),h.createUnableToFallbackToInteractionError();return s.error("useMsalAuthentication - Interaction required, falling back to interaction"),v(a,u)}throw e})))().then(e=>(A([e,null]),e)).catch(e=>{throw A([null,e]),e})},[c,e,n,s,d,v]);return t.useEffect(()=>{const e=c.addEventCallback(e=>{switch(e.eventType){case r.EventType.LOGIN_SUCCESS:case r.EventType.SSO_SILENT_SUCCESS:e.payload&&A([e.payload,null]);break;case r.EventType.LOGIN_FAILURE:case r.EventType.SSO_SILENT_FAILURE:e.error&&A([null,e.error])}});return s.verbose("useMsalAuthentication - Registered event callback with id: "+e),()=>{e&&(s.verbose("useMsalAuthentication - Removing event callback "+e),c.removeEventCallback(e))}},[c,s]),t.useEffect(()=>{m.current&&a===r.InteractionStatus.None&&(m.current=!1,i?d&&(s.info("useMsalAuthentication - User is authenticated, attempting to acquire token"),f().catch(()=>{})):(s.info("useMsalAuthentication - No user is authenticated, attempting to login"),v().catch(()=>{})))},[i,d,a,v,f,s]),{login:v,acquireToken:f,result:E,error:I}}exports.AuthenticatedTemplate=function({username:e,homeAccountId:o,localAccountId:c,children:s}){const i=u();return l(t.useMemo(()=>({username:e,homeAccountId:o,localAccountId:c}),[e,o,c]))&&i.inProgress!==r.InteractionStatus.Startup?n.createElement(n.Fragment,null,a(s,i)):null},exports.MsalAuthenticationTemplate=function({interactionType:e,username:o,homeAccountId:c,localAccountId:s,authenticationRequest:i,loadingComponent:d,errorComponent:p,children:h}){const I=t.useMemo(()=>({username:o,homeAccountId:c,localAccountId:s}),[o,c,s]),A=u(),g=E(e,i,I),m=l(I);if(g.error&&A.inProgress===r.InteractionStatus.None){if(p)return n.createElement(p,Object.assign({},g));throw g.error}return m?n.createElement(n.Fragment,null,a(h,g)):d&&A.inProgress!==r.InteractionStatus.None?n.createElement(d,Object.assign({},A)):null},exports.MsalConsumer=c,exports.MsalContext=o,exports.MsalProvider=function({instance:e,children:c}){t.useEffect(()=>{e.initializeWrapperLibrary(r.WrapperSKU.React,"1.3.0")},[e]);const a=t.useMemo(()=>e.getLogger().clone("@azure/msal-react","1.3.0"),[e]),[s,u]=t.useState(()=>e.getAllAccounts()),[i,l]=t.useState(r.InteractionStatus.Startup),d=t.useRef(i);return t.useEffect(()=>{const t=e.addEventCallback(t=>{switch(t.eventType){case r.EventType.ACCOUNT_ADDED:case r.EventType.ACCOUNT_REMOVED:case r.EventType.LOGIN_SUCCESS:case r.EventType.SSO_SILENT_SUCCESS:case r.EventType.HANDLE_REDIRECT_END:case r.EventType.LOGIN_FAILURE:case r.EventType.SSO_SILENT_FAILURE:case r.EventType.LOGOUT_END:case r.EventType.ACQUIRE_TOKEN_SUCCESS:case r.EventType.ACQUIRE_TOKEN_FAILURE:const t=e.getAllAccounts();!function(e,t){if(e.length!==t.length)return!1;const n=[...t];return e.every(e=>{const t=n.shift();return!(!e||!t)&&e.homeAccountId===t.homeAccountId&&e.localAccountId===t.localAccountId&&e.username===t.username})}(t,s)?(a.info("MsalProvider - updating account state"),u(t)):a.info("MsalProvider - no account changes")}});return a.verbose("MsalProvider - Registered event callback with id: "+t),()=>{t&&(a.verbose("MsalProvider - Removing event callback "+t),e.removeEventCallback(t))}},[e,s,a]),t.useEffect(()=>{const t=e.addEventCallback(e=>{const t=r.EventMessageUtils.getInteractionStatusFromEvent(e,d.current);null!==t&&(a.info(`MsalProvider - ${e.eventType} results in setting inProgress from ${d.current} to ${t}`),d.current=t,l(t))});return a.verbose("MsalProvider - Registered event callback with id: "+t),e.handleRedirectPromise().catch(()=>{}).finally(()=>{d.current===r.InteractionStatus.Startup&&(d.current=r.InteractionStatus.None,l(r.InteractionStatus.None))}),()=>{t&&(a.verbose("MsalProvider - Removing event callback "+t),e.removeEventCallback(t))}},[e,a]),n.createElement(o.Provider,{value:{instance:e,inProgress:i,accounts:s,logger:a}},c)},exports.UnauthenticatedTemplate=function({username:e,homeAccountId:o,localAccountId:c,children:s}){const i=u();return l(t.useMemo(()=>({username:e,homeAccountId:o,localAccountId:c}),[e,o,c]))||i.inProgress===r.InteractionStatus.Startup||i.inProgress===r.InteractionStatus.HandleRedirect?null:n.createElement(n.Fragment,null,a(s,i))},exports.useAccount=p,exports.useIsAuthenticated=l,exports.useMsal=u,exports.useMsalAuthentication=E,exports.version="1.3.0",exports.withMsal=e=>{const t=t=>{const r=u();return n.createElement(e,Object.assign({},t,{msalContext:r}))};return t.displayName=`withMsal(${e.displayName||e.name||"Component"})`,t};
//# sourceMappingURL=msal-react.cjs.production.min.js.map
import React__default, { createContext, useEffect, useMemo, useState, useRef, useContext, useCallback } from 'react';
import { stubbedPublicClientApplication, InteractionStatus, Logger, WrapperSKU, EventType, EventMessageUtils, AccountEntity, InteractionType } from '@azure/msal-browser';
import { stubbedPublicClientApplication, InteractionStatus, Logger, WrapperSKU, EventType, EventMessageUtils, AccountEntity, AuthError, InteractionType, InteractionRequiredAuthError, OIDC_DEFAULT_SCOPES } from '@azure/msal-browser';

@@ -56,6 +56,28 @@ /*

}
function getAccountByIdentifiers(allAccounts, accountIdentifiers) {
if (allAccounts.length > 0 && (accountIdentifiers.homeAccountId || accountIdentifiers.localAccountId || accountIdentifiers.username)) {
const matchedAccounts = allAccounts.filter(accountObj => {
if (accountIdentifiers.username && accountIdentifiers.username.toLowerCase() !== accountObj.username.toLowerCase()) {
return false;
}
if (accountIdentifiers.homeAccountId && accountIdentifiers.homeAccountId.toLowerCase() !== accountObj.homeAccountId.toLowerCase()) {
return false;
}
if (accountIdentifiers.localAccountId && accountIdentifiers.localAccountId.toLowerCase() !== accountObj.localAccountId.toLowerCase()) {
return false;
}
return true;
});
return matchedAccounts[0] || null;
} else {
return null;
}
}
/* eslint-disable header/header */
const name = "@azure/msal-react";
const version = "1.2.0";
const version = "1.3.0";

@@ -78,3 +100,3 @@ /*

const [accounts, setAccounts] = useState([]); // State hook to store in progress value
const [accounts, setAccounts] = useState(() => instance.getAllAccounts()); // State hook to store in progress value

@@ -175,57 +197,5 @@ const [inProgress, setInProgress] = useState(InteractionStatus.Startup); // Mutable object used in the event callback

function getAccount(instance, accountIdentifiers) {
const allAccounts = instance.getAllAccounts();
if (allAccounts.length > 0 && (accountIdentifiers.homeAccountId || accountIdentifiers.localAccountId || accountIdentifiers.username)) {
const matchedAccounts = allAccounts.filter(accountObj => {
if (accountIdentifiers.username && accountIdentifiers.username.toLowerCase() !== accountObj.username.toLowerCase()) {
return false;
}
if (accountIdentifiers.homeAccountId && accountIdentifiers.homeAccountId.toLowerCase() !== accountObj.homeAccountId.toLowerCase()) {
return false;
}
if (accountIdentifiers.localAccountId && accountIdentifiers.localAccountId.toLowerCase() !== accountObj.localAccountId.toLowerCase()) {
return false;
}
return true;
});
return matchedAccounts[0] || null;
} else {
return null;
}
}
/**
* Given 1 or more accountIdentifiers, returns the Account object if the user is signed-in
* @param accountIdentifiers
*/
function useAccount(accountIdentifiers) {
const {
instance,
inProgress
} = useMsal();
const initialStateValue = inProgress === InteractionStatus.Startup ? null : getAccount(instance, accountIdentifiers);
const [account, setAccount] = useState(initialStateValue);
useEffect(() => {
const currentAccount = getAccount(instance, accountIdentifiers);
if (!AccountEntity.accountInfoIsEqual(account, currentAccount, true)) {
setAccount(currentAccount);
}
}, [inProgress, accountIdentifiers, instance, account]);
return account;
}
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
function isAuthenticated(allAccounts, account, matchAccount) {
function isAuthenticated(allAccounts, matchAccount) {
if (matchAccount && (matchAccount.username || matchAccount.homeAccountId || matchAccount.localAccountId)) {
return !!account;
return !!getAccountByIdentifiers(allAccounts, matchAccount);
}

@@ -243,11 +213,8 @@

const {
accounts: allAccounts,
inProgress
accounts: allAccounts
} = useMsal();
const account = useAccount(matchAccount || {});
const initialStateValue = inProgress === InteractionStatus.Startup ? false : isAuthenticated(allAccounts, account, matchAccount);
const [hasAuthenticated, setHasAuthenticated] = useState(initialStateValue);
const [hasAuthenticated, setHasAuthenticated] = useState(() => isAuthenticated(allAccounts, matchAccount));
useEffect(() => {
setHasAuthenticated(isAuthenticated(allAccounts, account, matchAccount));
}, [allAccounts, account, matchAccount]);
setHasAuthenticated(isAuthenticated(allAccounts, matchAccount));
}, [allAccounts, matchAccount]);
return hasAuthenticated;

@@ -324,5 +291,78 @@ }

*/
function getAccount(instance, accountIdentifiers) {
if (!accountIdentifiers || !accountIdentifiers.homeAccountId && !accountIdentifiers.localAccountId && !accountIdentifiers.username) {
// If no account identifiers are provided, return active account
return instance.getActiveAccount();
}
return getAccountByIdentifiers(instance.getAllAccounts(), accountIdentifiers);
}
/**
* Invokes a login call if a user is not currently signed-in. Failed logins can be retried using the login callback returned.
* Optionally provide a request object to be used in the login call.
* Given 1 or more accountIdentifiers, returns the Account object if the user is signed-in
* @param accountIdentifiers
*/
function useAccount(accountIdentifiers) {
const {
instance,
inProgress,
logger
} = useMsal();
const [account, setAccount] = useState(() => getAccount(instance, accountIdentifiers));
useEffect(() => {
setAccount(currentAccount => {
const nextAccount = getAccount(instance, accountIdentifiers);
if (!AccountEntity.accountInfoIsEqual(currentAccount, nextAccount, true)) {
logger.info("useAccount - Updating account");
return nextAccount;
}
return currentAccount;
});
}, [inProgress, accountIdentifiers, instance, logger]);
return account;
}
/*
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License.
*/
const ReactAuthErrorMessage = {
invalidInteractionType: {
code: "invalid_interaction_type",
desc: "The provided interaction type is invalid."
},
unableToFallbackToInteraction: {
code: "unable_to_fallback_to_interaction",
desc: "Interaction is required but another interaction is already in progress. Please try again when the current interaction is complete."
}
};
class ReactAuthError extends AuthError {
constructor(errorCode, errorMessage) {
super(errorCode, errorMessage);
Object.setPrototypeOf(this, ReactAuthError.prototype);
this.name = "ReactAuthError";
}
static createInvalidInteractionTypeError() {
return new ReactAuthError(ReactAuthErrorMessage.invalidInteractionType.code, ReactAuthErrorMessage.invalidInteractionType.desc);
}
static createUnableToFallbackToInteractionError() {
return new ReactAuthError(ReactAuthErrorMessage.unableToFallbackToInteraction.code, ReactAuthErrorMessage.unableToFallbackToInteraction.desc);
}
}
/*
* 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.

@@ -341,4 +381,24 @@ * @param interactionType

const isAuthenticated = useIsAuthenticated(accountIdentifiers);
const [[result, error], setResponse] = useState([null, null]);
const [hasBeenCalled, setHasBeenCalled] = useState(false);
const account = useAccount(accountIdentifiers);
const [[result, error], setResponse] = useState([null, null]); // 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) => {

@@ -363,5 +423,55 @@ const loginType = callbackInteractionType || interactionType;

default:
throw "Invalid interaction type provided.";
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 => {
setResponse([response, null]);
return response;
}).catch(e => {
setResponse([null, e]);
throw e;
});
}, [instance, interactionType, authenticationRequest, logger, account, login]);
useEffect(() => {

@@ -396,14 +506,23 @@ const callbackId = instance.addEventCallback(message => {

useEffect(() => {
if (!hasBeenCalled && !error && !isAuthenticated && inProgress === InteractionStatus.None) {
logger.info("useMsalAuthentication - No user is authenticated, attempting to login"); // Ensure login is only called one time from within this hook, any subsequent login attempts should use the callback returned
if (shouldAcquireToken.current && inProgress === InteractionStatus.None) {
shouldAcquireToken.current = false;
setHasBeenCalled(true);
login().catch(() => {
// Errors are handled by the event handler above
return;
});
if (!isAuthenticated) {
logger.info("useMsalAuthentication - No user is authenticated, attempting to login");
login().catch(() => {
// Errors are saved in state above
return;
});
} else if (account) {
logger.info("useMsalAuthentication - User is authenticated, attempting to acquire token");
acquireToken().catch(() => {
// Errors are saved in state above
return;
});
}
}
}, [isAuthenticated, inProgress, error, hasBeenCalled, login, logger]);
}, [isAuthenticated, account, inProgress, login, acquireToken, logger]);
return {
login,
acquireToken,
result,

@@ -410,0 +529,0 @@ error

export declare const name = "@azure/msal-react";
export declare const version = "1.2.0";
export declare const version = "1.3.0";
/// <reference types="react" />
import { AccountIdentifiers } from "../types/AccountIdentifiers";
import { AccountInfo } from "@azure/msal-browser";
declare type FaaCFunction = <T>(args: T) => React.ReactNode;

@@ -15,2 +16,3 @@ export declare function getChildrenOrFunction<T>(children: React.ReactNode | FaaCFunction, args: T): React.ReactNode;

export declare function accountArraysAreEqual(arrayA: Array<AccountIdentifiers>, arrayB: Array<AccountIdentifiers>): boolean;
export declare function getAccountByIdentifiers(allAccounts: AccountInfo[], accountIdentifiers: AccountIdentifiers): AccountInfo | null;
export {};
{
"name": "@azure/msal-react",
"version": "1.2.0",
"version": "1.3.0",
"author": {

@@ -44,3 +44,3 @@ "name": "Microsoft",

"peerDependencies": {
"@azure/msal-browser": "^2.21.0",
"@azure/msal-browser": "^2.22.0",
"react": "^16.8.0 || ^17"

@@ -50,3 +50,3 @@ },

"devDependencies": {
"@azure/msal-browser": "^2.21.0",
"@azure/msal-browser": "^2.22.0",
"@testing-library/jest-dom": "^5.11.5",

@@ -53,0 +53,0 @@ "@testing-library/react": "^11.2.3",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc