@azure/msal-react 1.2.0 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/MsalProvider.d.ts +3 -0
- package/dist/error/ReactAuthError.d.ts +16 -0
- package/dist/hooks/useAccount.d.ts +1 -1
- package/dist/hooks/useMsalAuthentication.d.ts +6 -4
- package/dist/msal-react.cjs.development.js +314 -155
- package/dist/msal-react.cjs.development.js.map +1 -1
- package/dist/msal-react.cjs.production.min.js +1 -1
- package/dist/msal-react.cjs.production.min.js.map +1 -1
- package/dist/msal-react.esm.js +316 -157
- package/dist/msal-react.esm.js.map +1 -1
- package/dist/packageMetadata.d.ts +1 -1
- package/dist/utils/utilities.d.ts +2 -0
- package/package.json +9 -9
- package/CHANGELOG.json +0 -655
- package/CHANGELOG.md +0 -152
package/dist/MsalProvider.d.ts
CHANGED
|
@@ -3,4 +3,7 @@ import { IPublicClientApplication } from "@azure/msal-browser";
|
|
|
3
3
|
export declare type MsalProviderProps = PropsWithChildren<{
|
|
4
4
|
instance: IPublicClientApplication;
|
|
5
5
|
}>;
|
|
6
|
+
/**
|
|
7
|
+
* MSAL context provider component. This must be rendered above any other components that use MSAL.
|
|
8
|
+
*/
|
|
6
9
|
export declare function MsalProvider({ instance, children }: MsalProviderProps): React.ReactElement;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { AuthError } from "@azure/msal-browser";
|
|
2
|
+
export declare const ReactAuthErrorMessage: {
|
|
3
|
+
invalidInteractionType: {
|
|
4
|
+
code: string;
|
|
5
|
+
desc: string;
|
|
6
|
+
};
|
|
7
|
+
unableToFallbackToInteraction: {
|
|
8
|
+
code: string;
|
|
9
|
+
desc: string;
|
|
10
|
+
};
|
|
11
|
+
};
|
|
12
|
+
export declare class ReactAuthError extends AuthError {
|
|
13
|
+
constructor(errorCode: string, errorMessage?: string);
|
|
14
|
+
static createInvalidInteractionTypeError(): ReactAuthError;
|
|
15
|
+
static createUnableToFallbackToInteractionError(): ReactAuthError;
|
|
16
|
+
}
|
|
@@ -4,4 +4,4 @@ import { AccountIdentifiers } from "../types/AccountIdentifiers";
|
|
|
4
4
|
* Given 1 or more accountIdentifiers, returns the Account object if the user is signed-in
|
|
5
5
|
* @param accountIdentifiers
|
|
6
6
|
*/
|
|
7
|
-
export declare function useAccount(accountIdentifiers
|
|
7
|
+
export declare function useAccount(accountIdentifiers?: AccountIdentifiers): AccountInfo | null;
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { PopupRequest, RedirectRequest, SsoSilentRequest, InteractionType, AuthenticationResult, AuthError } from "@azure/msal-browser";
|
|
1
|
+
import { PopupRequest, RedirectRequest, SsoSilentRequest, InteractionType, AuthenticationResult, AuthError, SilentRequest } from "@azure/msal-browser";
|
|
2
2
|
import { AccountIdentifiers } from "../types/AccountIdentifiers";
|
|
3
3
|
export declare type MsalAuthenticationResult = {
|
|
4
|
-
login:
|
|
4
|
+
login: (callbackInteractionType?: InteractionType | undefined, callbackRequest?: PopupRequest | RedirectRequest | SilentRequest) => Promise<AuthenticationResult | null>;
|
|
5
|
+
acquireToken: (callbackInteractionType?: InteractionType | undefined, callbackRequest?: SilentRequest | undefined) => Promise<AuthenticationResult | null>;
|
|
5
6
|
result: AuthenticationResult | null;
|
|
6
7
|
error: AuthError | null;
|
|
7
8
|
};
|
|
8
9
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
10
|
+
* If a user is not currently signed in this hook invokes a login. Failed logins can be retried using the login callback returned.
|
|
11
|
+
* If a user is currently signed in this hook attempts to acquire a token. Subsequent token requests can use the acquireToken callback returned.
|
|
12
|
+
* Optionally provide a request object to be used in the login/acquireToken call.
|
|
11
13
|
* Optionally provide a specific user that should be logged in.
|
|
12
14
|
* @param interactionType
|
|
13
15
|
* @param authenticationRequest
|
|
@@ -60,75 +60,130 @@ function accountArraysAreEqual(arrayA, arrayB) {
|
|
|
60
60
|
return elementA.homeAccountId === elementB.homeAccountId && elementA.localAccountId === elementB.localAccountId && elementA.username === elementB.username;
|
|
61
61
|
});
|
|
62
62
|
}
|
|
63
|
+
function getAccountByIdentifiers(allAccounts, accountIdentifiers) {
|
|
64
|
+
if (allAccounts.length > 0 && (accountIdentifiers.homeAccountId || accountIdentifiers.localAccountId || accountIdentifiers.username)) {
|
|
65
|
+
const matchedAccounts = allAccounts.filter(accountObj => {
|
|
66
|
+
if (accountIdentifiers.username && accountIdentifiers.username.toLowerCase() !== accountObj.username.toLowerCase()) {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (accountIdentifiers.homeAccountId && accountIdentifiers.homeAccountId.toLowerCase() !== accountObj.homeAccountId.toLowerCase()) {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (accountIdentifiers.localAccountId && accountIdentifiers.localAccountId.toLowerCase() !== accountObj.localAccountId.toLowerCase()) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return true;
|
|
79
|
+
});
|
|
80
|
+
return matchedAccounts[0] || null;
|
|
81
|
+
} else {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
63
85
|
|
|
64
86
|
/* eslint-disable header/header */
|
|
65
87
|
const name = "@azure/msal-react";
|
|
66
|
-
const version = "1.2
|
|
88
|
+
const version = "1.3.2";
|
|
67
89
|
|
|
68
90
|
/*
|
|
69
91
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
70
92
|
* Licensed under the MIT License.
|
|
71
93
|
*/
|
|
72
|
-
|
|
73
|
-
instance,
|
|
74
|
-
children
|
|
75
|
-
}) {
|
|
76
|
-
React.useEffect(() => {
|
|
77
|
-
instance.initializeWrapperLibrary(msalBrowser.WrapperSKU.React, version);
|
|
78
|
-
}, [instance]); // Create a logger instance for msal-react with the same options as PublicClientApplication
|
|
94
|
+
var MsalProviderActionType;
|
|
79
95
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
96
|
+
(function (MsalProviderActionType) {
|
|
97
|
+
MsalProviderActionType["UNBLOCK_INPROGRESS"] = "UNBLOCK_INPROGRESS";
|
|
98
|
+
MsalProviderActionType["EVENT"] = "EVENT";
|
|
99
|
+
})(MsalProviderActionType || (MsalProviderActionType = {}));
|
|
100
|
+
/**
|
|
101
|
+
* Returns the next inProgress and accounts state based on event message
|
|
102
|
+
* @param previousState
|
|
103
|
+
* @param action
|
|
104
|
+
*/
|
|
83
105
|
|
|
84
|
-
const [accounts, setAccounts] = React.useState([]); // State hook to store in progress value
|
|
85
106
|
|
|
86
|
-
|
|
107
|
+
const reducer = (previousState, action) => {
|
|
108
|
+
const {
|
|
109
|
+
type,
|
|
110
|
+
payload
|
|
111
|
+
} = action;
|
|
112
|
+
let newAccounts = previousState.accounts;
|
|
113
|
+
let newInProgress = previousState.inProgress;
|
|
114
|
+
|
|
115
|
+
switch (type) {
|
|
116
|
+
case MsalProviderActionType.UNBLOCK_INPROGRESS:
|
|
117
|
+
if (previousState.inProgress === msalBrowser.InteractionStatus.Startup) {
|
|
118
|
+
newInProgress = msalBrowser.InteractionStatus.None;
|
|
119
|
+
payload.logger.info("MsalProvider - handleRedirectPromise resolved, setting inProgress to 'none'");
|
|
120
|
+
}
|
|
87
121
|
|
|
88
|
-
|
|
89
|
-
React.useEffect(() => {
|
|
90
|
-
const callbackId = instance.addEventCallback(message => {
|
|
91
|
-
switch (message.eventType) {
|
|
92
|
-
case msalBrowser.EventType.ACCOUNT_ADDED:
|
|
93
|
-
case msalBrowser.EventType.ACCOUNT_REMOVED:
|
|
94
|
-
case msalBrowser.EventType.LOGIN_SUCCESS:
|
|
95
|
-
case msalBrowser.EventType.SSO_SILENT_SUCCESS:
|
|
96
|
-
case msalBrowser.EventType.HANDLE_REDIRECT_END:
|
|
97
|
-
case msalBrowser.EventType.LOGIN_FAILURE:
|
|
98
|
-
case msalBrowser.EventType.SSO_SILENT_FAILURE:
|
|
99
|
-
case msalBrowser.EventType.LOGOUT_END:
|
|
100
|
-
case msalBrowser.EventType.ACQUIRE_TOKEN_SUCCESS:
|
|
101
|
-
case msalBrowser.EventType.ACQUIRE_TOKEN_FAILURE:
|
|
102
|
-
const currentAccounts = instance.getAllAccounts();
|
|
103
|
-
|
|
104
|
-
if (!accountArraysAreEqual(currentAccounts, accounts)) {
|
|
105
|
-
logger.info("MsalProvider - updating account state");
|
|
106
|
-
setAccounts(currentAccounts);
|
|
107
|
-
} else {
|
|
108
|
-
logger.info("MsalProvider - no account changes");
|
|
109
|
-
}
|
|
122
|
+
break;
|
|
110
123
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
logger.verbose(`MsalProvider - Removing event callback ${callbackId}`);
|
|
119
|
-
instance.removeEventCallback(callbackId);
|
|
124
|
+
case MsalProviderActionType.EVENT:
|
|
125
|
+
const message = payload.message;
|
|
126
|
+
const status = msalBrowser.EventMessageUtils.getInteractionStatusFromEvent(message, previousState.inProgress);
|
|
127
|
+
|
|
128
|
+
if (status) {
|
|
129
|
+
payload.logger.info(`MsalProvider - ${message.eventType} results in setting inProgress from ${previousState.inProgress} to ${status}`);
|
|
130
|
+
newInProgress = status;
|
|
120
131
|
}
|
|
132
|
+
|
|
133
|
+
break;
|
|
134
|
+
|
|
135
|
+
default:
|
|
136
|
+
throw new Error(`Unknown action type: ${type}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const currentAccounts = payload.instance.getAllAccounts();
|
|
140
|
+
|
|
141
|
+
if (!accountArraysAreEqual(currentAccounts, previousState.accounts)) {
|
|
142
|
+
payload.logger.info("MsalProvider - updating account state");
|
|
143
|
+
newAccounts = currentAccounts;
|
|
144
|
+
} else {
|
|
145
|
+
payload.logger.verbose("MsalProvider - no account changes");
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return { ...previousState,
|
|
149
|
+
inProgress: newInProgress,
|
|
150
|
+
accounts: newAccounts
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
/**
|
|
154
|
+
* MSAL context provider component. This must be rendered above any other components that use MSAL.
|
|
155
|
+
*/
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
function MsalProvider(_ref) {
|
|
159
|
+
let {
|
|
160
|
+
instance,
|
|
161
|
+
children
|
|
162
|
+
} = _ref;
|
|
163
|
+
React.useEffect(() => {
|
|
164
|
+
instance.initializeWrapperLibrary(msalBrowser.WrapperSKU.React, version);
|
|
165
|
+
}, [instance]); // Create a logger instance for msal-react with the same options as PublicClientApplication
|
|
166
|
+
|
|
167
|
+
const logger = React.useMemo(() => {
|
|
168
|
+
return instance.getLogger().clone(name, version);
|
|
169
|
+
}, [instance]);
|
|
170
|
+
const [state, updateState] = React.useReducer(reducer, undefined, () => {
|
|
171
|
+
// Lazy initialization of the initial state
|
|
172
|
+
return {
|
|
173
|
+
inProgress: msalBrowser.InteractionStatus.Startup,
|
|
174
|
+
accounts: instance.getAllAccounts()
|
|
121
175
|
};
|
|
122
|
-
}
|
|
176
|
+
});
|
|
123
177
|
React.useEffect(() => {
|
|
124
178
|
const callbackId = instance.addEventCallback(message => {
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
179
|
+
updateState({
|
|
180
|
+
payload: {
|
|
181
|
+
instance,
|
|
182
|
+
logger,
|
|
183
|
+
message
|
|
184
|
+
},
|
|
185
|
+
type: MsalProviderActionType.EVENT
|
|
186
|
+
});
|
|
132
187
|
});
|
|
133
188
|
logger.verbose(`MsalProvider - Registered event callback with id: ${callbackId}`);
|
|
134
189
|
instance.handleRedirectPromise().catch(() => {
|
|
@@ -139,12 +194,16 @@ function MsalProvider({
|
|
|
139
194
|
* If handleRedirectPromise returns a cached promise the necessary events may not be fired
|
|
140
195
|
* This is a fallback to prevent inProgress from getting stuck in 'startup'
|
|
141
196
|
*/
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
197
|
+
updateState({
|
|
198
|
+
payload: {
|
|
199
|
+
instance,
|
|
200
|
+
logger
|
|
201
|
+
},
|
|
202
|
+
type: MsalProviderActionType.UNBLOCK_INPROGRESS
|
|
203
|
+
});
|
|
146
204
|
});
|
|
147
205
|
return () => {
|
|
206
|
+
// Remove callback when component unmounts or accounts change
|
|
148
207
|
if (callbackId) {
|
|
149
208
|
logger.verbose(`MsalProvider - Removing event callback ${callbackId}`);
|
|
150
209
|
instance.removeEventCallback(callbackId);
|
|
@@ -153,8 +212,8 @@ function MsalProvider({
|
|
|
153
212
|
}, [instance, logger]);
|
|
154
213
|
const contextValue = {
|
|
155
214
|
instance,
|
|
156
|
-
inProgress,
|
|
157
|
-
accounts,
|
|
215
|
+
inProgress: state.inProgress,
|
|
216
|
+
accounts: state.accounts,
|
|
158
217
|
logger
|
|
159
218
|
};
|
|
160
219
|
return React__default.createElement(MsalContext.Provider, {
|
|
@@ -177,61 +236,9 @@ const useMsal = () => React.useContext(MsalContext);
|
|
|
177
236
|
* Licensed under the MIT License.
|
|
178
237
|
*/
|
|
179
238
|
|
|
180
|
-
function
|
|
181
|
-
const allAccounts = instance.getAllAccounts();
|
|
182
|
-
|
|
183
|
-
if (allAccounts.length > 0 && (accountIdentifiers.homeAccountId || accountIdentifiers.localAccountId || accountIdentifiers.username)) {
|
|
184
|
-
const matchedAccounts = allAccounts.filter(accountObj => {
|
|
185
|
-
if (accountIdentifiers.username && accountIdentifiers.username.toLowerCase() !== accountObj.username.toLowerCase()) {
|
|
186
|
-
return false;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
if (accountIdentifiers.homeAccountId && accountIdentifiers.homeAccountId.toLowerCase() !== accountObj.homeAccountId.toLowerCase()) {
|
|
190
|
-
return false;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
if (accountIdentifiers.localAccountId && accountIdentifiers.localAccountId.toLowerCase() !== accountObj.localAccountId.toLowerCase()) {
|
|
194
|
-
return false;
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return true;
|
|
198
|
-
});
|
|
199
|
-
return matchedAccounts[0] || null;
|
|
200
|
-
} else {
|
|
201
|
-
return null;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
/**
|
|
205
|
-
* Given 1 or more accountIdentifiers, returns the Account object if the user is signed-in
|
|
206
|
-
* @param accountIdentifiers
|
|
207
|
-
*/
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
function useAccount(accountIdentifiers) {
|
|
211
|
-
const {
|
|
212
|
-
instance,
|
|
213
|
-
inProgress
|
|
214
|
-
} = useMsal();
|
|
215
|
-
const initialStateValue = inProgress === msalBrowser.InteractionStatus.Startup ? null : getAccount(instance, accountIdentifiers);
|
|
216
|
-
const [account, setAccount] = React.useState(initialStateValue);
|
|
217
|
-
React.useEffect(() => {
|
|
218
|
-
const currentAccount = getAccount(instance, accountIdentifiers);
|
|
219
|
-
|
|
220
|
-
if (!msalBrowser.AccountEntity.accountInfoIsEqual(account, currentAccount, true)) {
|
|
221
|
-
setAccount(currentAccount);
|
|
222
|
-
}
|
|
223
|
-
}, [inProgress, accountIdentifiers, instance, account]);
|
|
224
|
-
return account;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
/*
|
|
228
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
229
|
-
* Licensed under the MIT License.
|
|
230
|
-
*/
|
|
231
|
-
|
|
232
|
-
function isAuthenticated(allAccounts, account, matchAccount) {
|
|
239
|
+
function isAuthenticated(allAccounts, matchAccount) {
|
|
233
240
|
if (matchAccount && (matchAccount.username || matchAccount.homeAccountId || matchAccount.localAccountId)) {
|
|
234
|
-
return !!
|
|
241
|
+
return !!getAccountByIdentifiers(allAccounts, matchAccount);
|
|
235
242
|
}
|
|
236
243
|
|
|
237
244
|
return allAccounts.length > 0;
|
|
@@ -244,15 +251,12 @@ function isAuthenticated(allAccounts, account, matchAccount) {
|
|
|
244
251
|
|
|
245
252
|
function useIsAuthenticated(matchAccount) {
|
|
246
253
|
const {
|
|
247
|
-
accounts: allAccounts
|
|
248
|
-
inProgress
|
|
254
|
+
accounts: allAccounts
|
|
249
255
|
} = useMsal();
|
|
250
|
-
const
|
|
251
|
-
const initialStateValue = inProgress === msalBrowser.InteractionStatus.Startup ? false : isAuthenticated(allAccounts, account, matchAccount);
|
|
252
|
-
const [hasAuthenticated, setHasAuthenticated] = React.useState(initialStateValue);
|
|
256
|
+
const [hasAuthenticated, setHasAuthenticated] = React.useState(() => isAuthenticated(allAccounts, matchAccount));
|
|
253
257
|
React.useEffect(() => {
|
|
254
|
-
setHasAuthenticated(isAuthenticated(allAccounts,
|
|
255
|
-
}, [allAccounts,
|
|
258
|
+
setHasAuthenticated(isAuthenticated(allAccounts, matchAccount));
|
|
259
|
+
}, [allAccounts, matchAccount]);
|
|
256
260
|
return hasAuthenticated;
|
|
257
261
|
}
|
|
258
262
|
|
|
@@ -265,12 +269,13 @@ function useIsAuthenticated(matchAccount) {
|
|
|
265
269
|
* @param props
|
|
266
270
|
*/
|
|
267
271
|
|
|
268
|
-
function AuthenticatedTemplate({
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
272
|
+
function AuthenticatedTemplate(_ref) {
|
|
273
|
+
let {
|
|
274
|
+
username,
|
|
275
|
+
homeAccountId,
|
|
276
|
+
localAccountId,
|
|
277
|
+
children
|
|
278
|
+
} = _ref;
|
|
274
279
|
const context = useMsal();
|
|
275
280
|
const accountIdentifier = React.useMemo(() => {
|
|
276
281
|
return {
|
|
@@ -297,12 +302,13 @@ function AuthenticatedTemplate({
|
|
|
297
302
|
* @param props
|
|
298
303
|
*/
|
|
299
304
|
|
|
300
|
-
function UnauthenticatedTemplate({
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
305
|
+
function UnauthenticatedTemplate(_ref) {
|
|
306
|
+
let {
|
|
307
|
+
username,
|
|
308
|
+
homeAccountId,
|
|
309
|
+
localAccountId,
|
|
310
|
+
children
|
|
311
|
+
} = _ref;
|
|
306
312
|
const context = useMsal();
|
|
307
313
|
const accountIdentifier = React.useMemo(() => {
|
|
308
314
|
return {
|
|
@@ -320,13 +326,86 @@ function UnauthenticatedTemplate({
|
|
|
320
326
|
return null;
|
|
321
327
|
}
|
|
322
328
|
|
|
329
|
+
/*
|
|
330
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
331
|
+
* Licensed under the MIT License.
|
|
332
|
+
*/
|
|
333
|
+
|
|
334
|
+
function getAccount(instance, accountIdentifiers) {
|
|
335
|
+
if (!accountIdentifiers || !accountIdentifiers.homeAccountId && !accountIdentifiers.localAccountId && !accountIdentifiers.username) {
|
|
336
|
+
// If no account identifiers are provided, return active account
|
|
337
|
+
return instance.getActiveAccount();
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
return getAccountByIdentifiers(instance.getAllAccounts(), accountIdentifiers);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Given 1 or more accountIdentifiers, returns the Account object if the user is signed-in
|
|
344
|
+
* @param accountIdentifiers
|
|
345
|
+
*/
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
function useAccount(accountIdentifiers) {
|
|
349
|
+
const {
|
|
350
|
+
instance,
|
|
351
|
+
inProgress,
|
|
352
|
+
logger
|
|
353
|
+
} = useMsal();
|
|
354
|
+
const [account, setAccount] = React.useState(() => getAccount(instance, accountIdentifiers));
|
|
355
|
+
React.useEffect(() => {
|
|
356
|
+
setAccount(currentAccount => {
|
|
357
|
+
const nextAccount = getAccount(instance, accountIdentifiers);
|
|
358
|
+
|
|
359
|
+
if (!msalBrowser.AccountEntity.accountInfoIsEqual(currentAccount, nextAccount, true)) {
|
|
360
|
+
logger.info("useAccount - Updating account");
|
|
361
|
+
return nextAccount;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return currentAccount;
|
|
365
|
+
});
|
|
366
|
+
}, [inProgress, accountIdentifiers, instance, logger]);
|
|
367
|
+
return account;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/*
|
|
371
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
372
|
+
* Licensed under the MIT License.
|
|
373
|
+
*/
|
|
374
|
+
const ReactAuthErrorMessage = {
|
|
375
|
+
invalidInteractionType: {
|
|
376
|
+
code: "invalid_interaction_type",
|
|
377
|
+
desc: "The provided interaction type is invalid."
|
|
378
|
+
},
|
|
379
|
+
unableToFallbackToInteraction: {
|
|
380
|
+
code: "unable_to_fallback_to_interaction",
|
|
381
|
+
desc: "Interaction is required but another interaction is already in progress. Please try again when the current interaction is complete."
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
class ReactAuthError extends msalBrowser.AuthError {
|
|
385
|
+
constructor(errorCode, errorMessage) {
|
|
386
|
+
super(errorCode, errorMessage);
|
|
387
|
+
Object.setPrototypeOf(this, ReactAuthError.prototype);
|
|
388
|
+
this.name = "ReactAuthError";
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
static createInvalidInteractionTypeError() {
|
|
392
|
+
return new ReactAuthError(ReactAuthErrorMessage.invalidInteractionType.code, ReactAuthErrorMessage.invalidInteractionType.desc);
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
static createUnableToFallbackToInteractionError() {
|
|
396
|
+
return new ReactAuthError(ReactAuthErrorMessage.unableToFallbackToInteraction.code, ReactAuthErrorMessage.unableToFallbackToInteraction.desc);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
}
|
|
400
|
+
|
|
323
401
|
/*
|
|
324
402
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
325
403
|
* Licensed under the MIT License.
|
|
326
404
|
*/
|
|
327
405
|
/**
|
|
328
|
-
*
|
|
329
|
-
*
|
|
406
|
+
* If a user is not currently signed in this hook invokes a login. Failed logins can be retried using the login callback returned.
|
|
407
|
+
* If a user is currently signed in this hook attempts to acquire a token. Subsequent token requests can use the acquireToken callback returned.
|
|
408
|
+
* Optionally provide a request object to be used in the login/acquireToken call.
|
|
330
409
|
* Optionally provide a specific user that should be logged in.
|
|
331
410
|
* @param interactionType
|
|
332
411
|
* @param authenticationRequest
|
|
@@ -340,8 +419,28 @@ function useMsalAuthentication(interactionType, authenticationRequest, accountId
|
|
|
340
419
|
logger
|
|
341
420
|
} = useMsal();
|
|
342
421
|
const isAuthenticated = useIsAuthenticated(accountIdentifiers);
|
|
343
|
-
const
|
|
344
|
-
const [
|
|
422
|
+
const account = useAccount(accountIdentifiers);
|
|
423
|
+
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
|
|
424
|
+
|
|
425
|
+
const interactionInProgress = React.useRef(inProgress !== msalBrowser.InteractionStatus.None);
|
|
426
|
+
React.useEffect(() => {
|
|
427
|
+
interactionInProgress.current = inProgress !== msalBrowser.InteractionStatus.None;
|
|
428
|
+
}, [inProgress]); // Flag used to control when the hook calls login/acquireToken
|
|
429
|
+
|
|
430
|
+
const shouldAcquireToken = React.useRef(true);
|
|
431
|
+
React.useEffect(() => {
|
|
432
|
+
if (!!error) {
|
|
433
|
+
// Errors should be handled by consuming component
|
|
434
|
+
shouldAcquireToken.current = false;
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
if (!!result) {
|
|
439
|
+
// Token has already been acquired, consuming component/application is responsible for renewing
|
|
440
|
+
shouldAcquireToken.current = false;
|
|
441
|
+
return;
|
|
442
|
+
}
|
|
443
|
+
}, [error, result]);
|
|
345
444
|
const login = React.useCallback(async (callbackInteractionType, callbackRequest) => {
|
|
346
445
|
const loginType = callbackInteractionType || interactionType;
|
|
347
446
|
const loginRequest = callbackRequest || authenticationRequest;
|
|
@@ -361,9 +460,59 @@ function useMsalAuthentication(interactionType, authenticationRequest, accountId
|
|
|
361
460
|
return instance.ssoSilent(loginRequest);
|
|
362
461
|
|
|
363
462
|
default:
|
|
364
|
-
throw
|
|
463
|
+
throw ReactAuthError.createInvalidInteractionTypeError();
|
|
365
464
|
}
|
|
366
465
|
}, [instance, interactionType, authenticationRequest, logger]);
|
|
466
|
+
const acquireToken = React.useCallback(async (callbackInteractionType, callbackRequest) => {
|
|
467
|
+
const fallbackInteractionType = callbackInteractionType || interactionType;
|
|
468
|
+
let tokenRequest;
|
|
469
|
+
|
|
470
|
+
if (callbackRequest) {
|
|
471
|
+
logger.trace("useMsalAuthentication - acquireToken - Using request provided in the callback");
|
|
472
|
+
tokenRequest = { ...callbackRequest
|
|
473
|
+
};
|
|
474
|
+
} else if (authenticationRequest) {
|
|
475
|
+
logger.trace("useMsalAuthentication - acquireToken - Using request provided in the hook");
|
|
476
|
+
tokenRequest = { ...authenticationRequest,
|
|
477
|
+
scopes: authenticationRequest.scopes || msalBrowser.OIDC_DEFAULT_SCOPES
|
|
478
|
+
};
|
|
479
|
+
} else {
|
|
480
|
+
logger.trace("useMsalAuthentication - acquireToken - No request object provided, using default request.");
|
|
481
|
+
tokenRequest = {
|
|
482
|
+
scopes: msalBrowser.OIDC_DEFAULT_SCOPES
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (!tokenRequest.account && account) {
|
|
487
|
+
logger.trace("useMsalAuthentication - acquireToken - Attaching account to request");
|
|
488
|
+
tokenRequest.account = account;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
const getToken = async () => {
|
|
492
|
+
logger.verbose("useMsalAuthentication - Calling acquireTokenSilent");
|
|
493
|
+
return instance.acquireTokenSilent(tokenRequest).catch(async e => {
|
|
494
|
+
if (e instanceof msalBrowser.InteractionRequiredAuthError) {
|
|
495
|
+
if (!interactionInProgress.current) {
|
|
496
|
+
logger.error("useMsalAuthentication - Interaction required, falling back to interaction");
|
|
497
|
+
return login(fallbackInteractionType, tokenRequest);
|
|
498
|
+
} else {
|
|
499
|
+
logger.error("useMsalAuthentication - Interaction required but is already in progress. Please try again, if needed, after interaction completes.");
|
|
500
|
+
throw ReactAuthError.createUnableToFallbackToInteractionError();
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
throw e;
|
|
505
|
+
});
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
return getToken().then(response => {
|
|
509
|
+
setResponse([response, null]);
|
|
510
|
+
return response;
|
|
511
|
+
}).catch(e => {
|
|
512
|
+
setResponse([null, e]);
|
|
513
|
+
throw e;
|
|
514
|
+
});
|
|
515
|
+
}, [instance, interactionType, authenticationRequest, logger, account, login]);
|
|
367
516
|
React.useEffect(() => {
|
|
368
517
|
const callbackId = instance.addEventCallback(message => {
|
|
369
518
|
switch (message.eventType) {
|
|
@@ -393,18 +542,27 @@ function useMsalAuthentication(interactionType, authenticationRequest, accountId
|
|
|
393
542
|
};
|
|
394
543
|
}, [instance, logger]);
|
|
395
544
|
React.useEffect(() => {
|
|
396
|
-
if (
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
545
|
+
if (shouldAcquireToken.current && inProgress === msalBrowser.InteractionStatus.None) {
|
|
546
|
+
shouldAcquireToken.current = false;
|
|
547
|
+
|
|
548
|
+
if (!isAuthenticated) {
|
|
549
|
+
logger.info("useMsalAuthentication - No user is authenticated, attempting to login");
|
|
550
|
+
login().catch(() => {
|
|
551
|
+
// Errors are saved in state above
|
|
552
|
+
return;
|
|
553
|
+
});
|
|
554
|
+
} else if (account) {
|
|
555
|
+
logger.info("useMsalAuthentication - User is authenticated, attempting to acquire token");
|
|
556
|
+
acquireToken().catch(() => {
|
|
557
|
+
// Errors are saved in state above
|
|
558
|
+
return;
|
|
559
|
+
});
|
|
560
|
+
}
|
|
404
561
|
}
|
|
405
|
-
}, [isAuthenticated,
|
|
562
|
+
}, [isAuthenticated, account, inProgress, login, acquireToken, logger]);
|
|
406
563
|
return {
|
|
407
564
|
login,
|
|
565
|
+
acquireToken,
|
|
408
566
|
result,
|
|
409
567
|
error
|
|
410
568
|
};
|
|
@@ -419,16 +577,17 @@ function useMsalAuthentication(interactionType, authenticationRequest, accountId
|
|
|
419
577
|
* @param props
|
|
420
578
|
*/
|
|
421
579
|
|
|
422
|
-
function MsalAuthenticationTemplate({
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
580
|
+
function MsalAuthenticationTemplate(_ref) {
|
|
581
|
+
let {
|
|
582
|
+
interactionType,
|
|
583
|
+
username,
|
|
584
|
+
homeAccountId,
|
|
585
|
+
localAccountId,
|
|
586
|
+
authenticationRequest,
|
|
587
|
+
loadingComponent: LoadingComponent,
|
|
588
|
+
errorComponent: ErrorComponent,
|
|
589
|
+
children
|
|
590
|
+
} = _ref;
|
|
432
591
|
const accountIdentifier = React.useMemo(() => {
|
|
433
592
|
return {
|
|
434
593
|
username,
|