@azure/msal-react 3.0.19 → 5.0.0-alpha.0

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.
Files changed (37) hide show
  1. package/README.md +5 -4
  2. package/dist/MsalContext.js +1 -1
  3. package/dist/MsalContext.js.map +1 -1
  4. package/dist/MsalProvider.js +5 -5
  5. package/dist/MsalProvider.js.map +1 -1
  6. package/dist/components/AuthenticatedTemplate.js +1 -1
  7. package/dist/components/AuthenticatedTemplate.js.map +1 -1
  8. package/dist/components/MsalAuthenticationTemplate.js +1 -1
  9. package/dist/components/MsalAuthenticationTemplate.js.map +1 -1
  10. package/dist/components/UnauthenticatedTemplate.js +1 -1
  11. package/dist/components/UnauthenticatedTemplate.js.map +1 -1
  12. package/dist/components/withMsal.js +1 -1
  13. package/dist/components/withMsal.js.map +1 -1
  14. package/dist/error/ReactAuthError.js +1 -1
  15. package/dist/error/ReactAuthError.js.map +1 -1
  16. package/dist/hooks/useAccount.js +27 -12
  17. package/dist/hooks/useAccount.js.map +1 -1
  18. package/dist/hooks/useIsAuthenticated.js +1 -1
  19. package/dist/hooks/useIsAuthenticated.js.map +1 -1
  20. package/dist/hooks/useMsal.js +1 -1
  21. package/dist/hooks/useMsal.js.map +1 -1
  22. package/dist/hooks/useMsalAuthentication.js +69 -72
  23. package/dist/hooks/useMsalAuthentication.js.map +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/packageMetadata.d.ts +1 -1
  26. package/dist/packageMetadata.js +2 -2
  27. package/dist/tsdoc-metadata.json +1 -1
  28. package/dist/utils/utilities.js +1 -1
  29. package/dist/utils/utilities.js.map +1 -1
  30. package/lib/msal-react.cjs +97 -85
  31. package/lib/msal-react.cjs.map +1 -1
  32. package/lib/types/packageMetadata.d.ts +1 -1
  33. package/package.json +81 -83
  34. package/src/MsalProvider.tsx +8 -4
  35. package/src/hooks/useAccount.ts +39 -15
  36. package/src/hooks/useMsalAuthentication.ts +106 -95
  37. package/src/packageMetadata.ts +1 -1
@@ -3,12 +3,15 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- import { useState, useEffect } from "react";
6
+ import { useState, useEffect, useCallback } from "react";
7
7
  import {
8
8
  AccountInfo,
9
9
  IPublicClientApplication,
10
- AccountEntity,
10
+ AccountEntityUtils,
11
11
  InteractionStatus,
12
+ EventMessage,
13
+ EventType,
14
+ InteractionType,
12
15
  } from "@azure/msal-browser";
13
16
  import { useMsal } from "./useMsal.js";
14
17
  import { AccountIdentifiers } from "../types/AccountIdentifiers.js";
@@ -51,25 +54,46 @@ export function useAccount(
51
54
  }
52
55
  });
53
56
 
57
+ const updateAccount = useCallback(() => {
58
+ const nextAccount = getAccount(instance, accountIdentifiers);
59
+ setAccount((currentAccount: AccountInfo | null) => {
60
+ if (
61
+ !AccountEntityUtils.accountInfoIsEqual(
62
+ currentAccount,
63
+ nextAccount,
64
+ true
65
+ )
66
+ ) {
67
+ logger.info("useAccount - Updating account", "");
68
+ return nextAccount;
69
+ }
70
+ return currentAccount;
71
+ });
72
+ }, [accountIdentifiers, instance, logger]);
73
+
54
74
  useEffect(() => {
55
75
  if (inProgress !== InteractionStatus.Startup) {
56
- setAccount((currentAccount: AccountInfo | null) => {
57
- const nextAccount = getAccount(instance, accountIdentifiers);
76
+ updateAccount();
77
+ }
78
+
79
+ const callbackId = instance.addEventCallback(
80
+ (message: EventMessage) => {
58
81
  if (
59
- !AccountEntity.accountInfoIsEqual(
60
- currentAccount,
61
- nextAccount,
62
- true
63
- )
82
+ message.eventType === EventType.ACTIVE_ACCOUNT_CHANGED ||
83
+ (message.eventType === EventType.LOGIN_SUCCESS &&
84
+ message.interactionType === InteractionType.Silent)
64
85
  ) {
65
- logger.info("useAccount - Updating account");
66
- return nextAccount;
86
+ updateAccount();
67
87
  }
88
+ }
89
+ );
68
90
 
69
- return currentAccount;
70
- });
71
- }
72
- }, [inProgress, accountIdentifiers, instance, logger]);
91
+ return () => {
92
+ if (callbackId) {
93
+ instance.removeEventCallback(callbackId);
94
+ }
95
+ };
96
+ }, [updateAccount, inProgress, instance]);
73
97
 
74
98
  return account;
75
99
  }
@@ -11,12 +11,11 @@ import {
11
11
  InteractionType,
12
12
  AuthenticationResult,
13
13
  AuthError,
14
- EventMessage,
15
- EventType,
16
14
  InteractionStatus,
17
15
  SilentRequest,
18
16
  InteractionRequiredAuthError,
19
17
  OIDC_DEFAULT_SCOPES,
18
+ BrowserUtils,
20
19
  } from "@azure/msal-browser";
21
20
  import { useIsAuthenticated } from "./useIsAuthenticated.js";
22
21
  import { AccountIdentifiers } from "../types/AccountIdentifiers.js";
@@ -95,26 +94,66 @@ export function useMsalAuthentication(
95
94
  ): Promise<AuthenticationResult | null> => {
96
95
  const loginType = callbackInteractionType || interactionType;
97
96
  const loginRequest = callbackRequest || authenticationRequest;
98
- switch (loginType) {
99
- case InteractionType.Popup:
100
- logger.verbose(
101
- "useMsalAuthentication - Calling loginPopup"
102
- );
103
- return instance.loginPopup(loginRequest as PopupRequest);
104
- case InteractionType.Redirect:
105
- // This promise is not expected to resolve due to full frame redirect
106
- logger.verbose(
107
- "useMsalAuthentication - Calling loginRedirect"
108
- );
109
- return instance
110
- .loginRedirect(loginRequest as RedirectRequest)
111
- .then(null);
112
- case InteractionType.Silent:
113
- logger.verbose("useMsalAuthentication - Calling ssoSilent");
114
- return instance.ssoSilent(loginRequest as SsoSilentRequest);
115
- default:
116
- throw ReactAuthError.createInvalidInteractionTypeError();
117
- }
97
+
98
+ const getToken = async (): Promise<AuthenticationResult | null> => {
99
+ logger.verbose(
100
+ "useMsalAuthentication - Calling getToken",
101
+ callbackRequest?.correlationId || ""
102
+ );
103
+
104
+ switch (loginType) {
105
+ case InteractionType.Popup:
106
+ logger.verbose(
107
+ "useMsalAuthentication - Calling loginPopup",
108
+ callbackRequest?.correlationId || ""
109
+ );
110
+ return instance.loginPopup(
111
+ loginRequest as PopupRequest
112
+ );
113
+
114
+ case InteractionType.Redirect:
115
+ // This promise is not expected to resolve due to full frame redirect
116
+ logger.verbose(
117
+ "useMsalAuthentication - Calling loginRedirect",
118
+ callbackRequest?.correlationId || ""
119
+ );
120
+ await instance.handleRedirectPromise();
121
+ return instance
122
+ .loginRedirect(loginRequest as RedirectRequest)
123
+ .then(() => null);
124
+
125
+ case InteractionType.Silent:
126
+ logger.verbose(
127
+ "useMsalAuthentication - Calling ssoSilent",
128
+ callbackRequest?.correlationId || ""
129
+ );
130
+ return instance.ssoSilent(
131
+ loginRequest as SsoSilentRequest
132
+ );
133
+
134
+ default:
135
+ const invalidTypeError =
136
+ ReactAuthError.createInvalidInteractionTypeError();
137
+ if (mounted.current) {
138
+ setResponse([null, invalidTypeError]);
139
+ }
140
+ throw invalidTypeError;
141
+ }
142
+ };
143
+
144
+ return getToken()
145
+ .then((response: AuthenticationResult | null) => {
146
+ if (response && mounted.current) {
147
+ setResponse([response, null]);
148
+ }
149
+ return response;
150
+ })
151
+ .catch((e: AuthError) => {
152
+ if (mounted.current) {
153
+ setResponse([null, e]);
154
+ }
155
+ throw e;
156
+ });
118
157
  },
119
158
  [instance, interactionType, authenticationRequest, logger]
120
159
  );
@@ -131,14 +170,16 @@ export function useMsalAuthentication(
131
170
 
132
171
  if (callbackRequest) {
133
172
  logger.trace(
134
- "useMsalAuthentication - acquireToken - Using request provided in the callback"
173
+ "useMsalAuthentication - acquireToken - Using request provided in the callback",
174
+ callbackRequest.correlationId || ""
135
175
  );
136
176
  tokenRequest = {
137
177
  ...callbackRequest,
138
178
  };
139
179
  } else if (authenticationRequest) {
140
180
  logger.trace(
141
- "useMsalAuthentication - acquireToken - Using request provided in the hook"
181
+ "useMsalAuthentication - acquireToken - Using request provided in the hook",
182
+ authenticationRequest.correlationId || ""
142
183
  );
143
184
  tokenRequest = {
144
185
  ...authenticationRequest,
@@ -146,56 +187,57 @@ export function useMsalAuthentication(
146
187
  };
147
188
  } else {
148
189
  logger.trace(
149
- "useMsalAuthentication - acquireToken - No request object provided, using default request."
190
+ "useMsalAuthentication - acquireToken - No request object provided, using default request.",
191
+ ""
150
192
  );
151
193
  tokenRequest = {
152
194
  scopes: OIDC_DEFAULT_SCOPES,
153
195
  };
154
196
  }
155
197
 
198
+ const correlationId =
199
+ tokenRequest.correlationId || BrowserUtils.createGuid();
200
+ tokenRequest.correlationId = correlationId;
201
+
156
202
  if (!tokenRequest.account && account) {
157
203
  logger.trace(
158
- "useMsalAuthentication - acquireToken - Attaching account to request"
204
+ "useMsalAuthentication - acquireToken - Attaching account to request",
205
+ correlationId
159
206
  );
160
207
  tokenRequest.account = account;
161
208
  }
162
209
 
163
- const getToken = async (): Promise<AuthenticationResult | null> => {
164
- logger.verbose(
165
- "useMsalAuthentication - Calling acquireTokenSilent"
166
- );
167
- return instance
168
- .acquireTokenSilent(tokenRequest)
169
- .catch(async (e: AuthError) => {
170
- if (e instanceof InteractionRequiredAuthError) {
171
- if (!interactionInProgress.current) {
172
- logger.error(
173
- "useMsalAuthentication - Interaction required, falling back to interaction"
174
- );
175
- return login(
176
- fallbackInteractionType,
177
- tokenRequest
178
- );
179
- } else {
180
- logger.error(
181
- "useMsalAuthentication - Interaction required but is already in progress. Please try again, if needed, after interaction completes."
182
- );
183
- throw ReactAuthError.createUnableToFallbackToInteractionError();
184
- }
185
- }
186
-
187
- throw e;
188
- });
189
- };
190
-
191
- return getToken()
192
- .then((response: AuthenticationResult | null) => {
210
+ return instance
211
+ .acquireTokenSilent(tokenRequest)
212
+ .then((response: AuthenticationResult) => {
193
213
  if (mounted.current) {
194
214
  setResponse([response, null]);
195
215
  }
196
216
  return response;
197
217
  })
198
- .catch((e: AuthError) => {
218
+ .catch(async (e: AuthError) => {
219
+ if (e instanceof InteractionRequiredAuthError) {
220
+ if (!interactionInProgress.current) {
221
+ logger.error(
222
+ "useMsalAuthentication - Interaction required, falling back to interaction",
223
+ correlationId
224
+ );
225
+ return login(fallbackInteractionType, tokenRequest);
226
+ } else {
227
+ const fallbackError =
228
+ ReactAuthError.createUnableToFallbackToInteractionError();
229
+ logger.error(
230
+ "useMsalAuthentication - Interaction required but is already in progress. Please try again, if needed, after interaction completes.",
231
+ correlationId
232
+ );
233
+ if (mounted.current) {
234
+ setResponse([null, fallbackError]);
235
+ }
236
+ throw fallbackError;
237
+ }
238
+ }
239
+
240
+ // Handle other errors
199
241
  if (mounted.current) {
200
242
  setResponse([null, e]);
201
243
  }
@@ -212,42 +254,6 @@ export function useMsalAuthentication(
212
254
  ]
213
255
  );
214
256
 
215
- useEffect(() => {
216
- const callbackId = instance.addEventCallback(
217
- (message: EventMessage) => {
218
- switch (message.eventType) {
219
- case EventType.LOGIN_SUCCESS:
220
- case EventType.SSO_SILENT_SUCCESS:
221
- if (message.payload) {
222
- setResponse([
223
- message.payload as AuthenticationResult,
224
- null,
225
- ]);
226
- }
227
- break;
228
- case EventType.LOGIN_FAILURE:
229
- case EventType.SSO_SILENT_FAILURE:
230
- if (message.error) {
231
- setResponse([null, message.error as AuthError]);
232
- }
233
- break;
234
- }
235
- }
236
- );
237
- logger.verbose(
238
- `useMsalAuthentication - Registered event callback with id: ${callbackId}`
239
- );
240
-
241
- return () => {
242
- if (callbackId) {
243
- logger.verbose(
244
- `useMsalAuthentication - Removing event callback ${callbackId}`
245
- );
246
- instance.removeEventCallback(callbackId);
247
- }
248
- };
249
- }, [instance, logger]);
250
-
251
257
  useEffect(() => {
252
258
  if (
253
259
  shouldAcquireToken.current &&
@@ -256,7 +262,8 @@ export function useMsalAuthentication(
256
262
  if (!isAuthenticated) {
257
263
  shouldAcquireToken.current = false;
258
264
  logger.info(
259
- "useMsalAuthentication - No user is authenticated, attempting to login"
265
+ "useMsalAuthentication - No user is authenticated, attempting to login",
266
+ ""
260
267
  );
261
268
  login().catch(() => {
262
269
  // Errors are saved in state above
@@ -265,13 +272,17 @@ export function useMsalAuthentication(
265
272
  } else if (account) {
266
273
  shouldAcquireToken.current = false;
267
274
  logger.info(
268
- "useMsalAuthentication - User is authenticated, attempting to acquire token"
275
+ "useMsalAuthentication - User is authenticated, attempting to acquire token",
276
+ ""
269
277
  );
270
278
  acquireToken().catch(() => {
271
279
  // Errors are saved in state above
272
280
  return;
273
281
  });
274
282
  }
283
+ // If logging out, set the state to null so the component doesn't display authenticated content for a user that is logged out
284
+ } else if (!account && result) {
285
+ setResponse([null, null]);
275
286
  }
276
287
  }, [isAuthenticated, account, inProgress, login, acquireToken, logger]);
277
288
 
@@ -1,3 +1,3 @@
1
1
  /* eslint-disable header/header */
2
2
  export const name = "@azure/msal-react";
3
- export const version = "3.0.19";
3
+ export const version = "5.0.0-alpha.0";