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