@azure/msal-browser 3.13.0 → 3.15.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 (153) hide show
  1. package/dist/app/IPublicClientApplication.d.ts +2 -1
  2. package/dist/app/IPublicClientApplication.d.ts.map +1 -1
  3. package/dist/app/IPublicClientApplication.mjs +4 -1
  4. package/dist/app/IPublicClientApplication.mjs.map +1 -1
  5. package/dist/app/PublicClientApplication.d.ts +17 -0
  6. package/dist/app/PublicClientApplication.d.ts.map +1 -1
  7. package/dist/app/PublicClientApplication.mjs +37 -9
  8. package/dist/app/PublicClientApplication.mjs.map +1 -1
  9. package/dist/app/PublicClientNext.d.ts +3 -0
  10. package/dist/app/PublicClientNext.d.ts.map +1 -1
  11. package/dist/app/PublicClientNext.mjs +4 -1
  12. package/dist/app/PublicClientNext.mjs.map +1 -1
  13. package/dist/broker/nativeBroker/NativeMessageHandler.mjs +1 -1
  14. package/dist/broker/nativeBroker/NativeStatusCodes.mjs +1 -1
  15. package/dist/cache/AccountManager.d.ts +49 -0
  16. package/dist/cache/AccountManager.d.ts.map +1 -0
  17. package/dist/cache/AccountManager.mjs +131 -0
  18. package/dist/cache/AccountManager.mjs.map +1 -0
  19. package/dist/cache/AsyncMemoryStorage.mjs +1 -1
  20. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  21. package/dist/cache/BrowserCacheManager.mjs +9 -2
  22. package/dist/cache/BrowserCacheManager.mjs.map +1 -1
  23. package/dist/cache/BrowserStorage.mjs +1 -1
  24. package/dist/cache/DatabaseStorage.mjs +1 -1
  25. package/dist/cache/MemoryStorage.mjs +1 -1
  26. package/dist/cache/TokenCache.mjs +1 -1
  27. package/dist/config/Configuration.d.ts +3 -1
  28. package/dist/config/Configuration.d.ts.map +1 -1
  29. package/dist/config/Configuration.mjs +1 -1
  30. package/dist/config/Configuration.mjs.map +1 -1
  31. package/dist/controllers/ControllerFactory.d.ts.map +1 -1
  32. package/dist/controllers/ControllerFactory.mjs +10 -12
  33. package/dist/controllers/ControllerFactory.mjs.map +1 -1
  34. package/dist/controllers/NestedAppAuthController.d.ts +118 -10
  35. package/dist/controllers/NestedAppAuthController.d.ts.map +1 -1
  36. package/dist/controllers/NestedAppAuthController.mjs +227 -83
  37. package/dist/controllers/NestedAppAuthController.mjs.map +1 -1
  38. package/dist/controllers/StandardController.d.ts.map +1 -1
  39. package/dist/controllers/StandardController.mjs +98 -115
  40. package/dist/controllers/StandardController.mjs.map +1 -1
  41. package/dist/controllers/UnknownOperatingContextController.mjs +1 -1
  42. package/dist/crypto/BrowserCrypto.mjs +1 -1
  43. package/dist/crypto/CryptoOps.mjs +1 -1
  44. package/dist/crypto/PkceGenerator.mjs +1 -1
  45. package/dist/crypto/SignedHttpRequest.mjs +1 -1
  46. package/dist/encode/Base64Decode.mjs +1 -1
  47. package/dist/encode/Base64Encode.mjs +1 -1
  48. package/dist/error/BrowserAuthError.mjs +1 -1
  49. package/dist/error/BrowserAuthErrorCodes.mjs +1 -1
  50. package/dist/error/BrowserConfigurationAuthError.mjs +1 -1
  51. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +1 -1
  52. package/dist/error/NativeAuthError.mjs +1 -1
  53. package/dist/error/NativeAuthErrorCodes.mjs +1 -1
  54. package/dist/error/NestedAppAuthError.mjs +1 -1
  55. package/dist/event/EventHandler.mjs +1 -1
  56. package/dist/event/EventMessage.mjs +1 -1
  57. package/dist/event/EventType.mjs +1 -1
  58. package/dist/index.d.ts +1 -1
  59. package/dist/index.d.ts.map +1 -1
  60. package/dist/index.mjs +2 -2
  61. package/dist/interaction_client/BaseInteractionClient.mjs +1 -1
  62. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
  63. package/dist/interaction_client/NativeInteractionClient.mjs +1 -1
  64. package/dist/interaction_client/PopupClient.mjs +1 -1
  65. package/dist/interaction_client/RedirectClient.d.ts +4 -5
  66. package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
  67. package/dist/interaction_client/RedirectClient.mjs +5 -8
  68. package/dist/interaction_client/RedirectClient.mjs.map +1 -1
  69. package/dist/interaction_client/SilentAuthCodeClient.mjs +1 -1
  70. package/dist/interaction_client/SilentCacheClient.mjs +1 -1
  71. package/dist/interaction_client/SilentIframeClient.mjs +1 -1
  72. package/dist/interaction_client/SilentRefreshClient.mjs +1 -1
  73. package/dist/interaction_client/StandardInteractionClient.mjs +1 -1
  74. package/dist/interaction_handler/InteractionHandler.mjs +1 -1
  75. package/dist/interaction_handler/RedirectHandler.mjs +1 -1
  76. package/dist/interaction_handler/SilentHandler.mjs +1 -1
  77. package/dist/naa/BridgeAccountContext.d.ts +13 -0
  78. package/dist/naa/BridgeAccountContext.d.ts.map +1 -0
  79. package/dist/naa/BridgeCapabilities.d.ts +1 -1
  80. package/dist/naa/BridgeCapabilities.d.ts.map +1 -1
  81. package/dist/naa/BridgeError.mjs +1 -1
  82. package/dist/naa/BridgeProxy.d.ts +3 -2
  83. package/dist/naa/BridgeProxy.d.ts.map +1 -1
  84. package/dist/naa/BridgeProxy.mjs +9 -7
  85. package/dist/naa/BridgeProxy.mjs.map +1 -1
  86. package/dist/naa/BridgeRequestEnvelope.d.ts +1 -1
  87. package/dist/naa/BridgeRequestEnvelope.d.ts.map +1 -1
  88. package/dist/naa/BridgeStatusCode.mjs +1 -1
  89. package/dist/naa/IBridgeProxy.d.ts +2 -2
  90. package/dist/naa/IBridgeProxy.d.ts.map +1 -1
  91. package/dist/naa/InitContext.d.ts +2 -0
  92. package/dist/naa/InitContext.d.ts.map +1 -1
  93. package/dist/naa/mapping/NestedAppAuthAdapter.d.ts +12 -2
  94. package/dist/naa/mapping/NestedAppAuthAdapter.d.ts.map +1 -1
  95. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +43 -6
  96. package/dist/naa/mapping/NestedAppAuthAdapter.mjs.map +1 -1
  97. package/dist/navigation/NavigationClient.mjs +1 -1
  98. package/dist/network/FetchClient.mjs +1 -1
  99. package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
  100. package/dist/operatingcontext/{TeamsAppOperatingContext.d.ts → NestedAppOperatingContext.d.ts} +8 -6
  101. package/dist/operatingcontext/NestedAppOperatingContext.d.ts.map +1 -0
  102. package/dist/operatingcontext/{TeamsAppOperatingContext.mjs → NestedAppOperatingContext.mjs} +21 -35
  103. package/dist/operatingcontext/NestedAppOperatingContext.mjs.map +1 -0
  104. package/dist/operatingcontext/StandardOperatingContext.d.ts.map +1 -1
  105. package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
  106. package/dist/operatingcontext/StandardOperatingContext.mjs.map +1 -1
  107. package/dist/operatingcontext/UnknownOperatingContext.d.ts +5 -5
  108. package/dist/operatingcontext/UnknownOperatingContext.d.ts.map +1 -1
  109. package/dist/operatingcontext/UnknownOperatingContext.mjs +8 -8
  110. package/dist/operatingcontext/UnknownOperatingContext.mjs.map +1 -1
  111. package/dist/packageMetadata.d.ts +1 -1
  112. package/dist/packageMetadata.mjs +2 -2
  113. package/dist/request/RequestHelpers.mjs +1 -1
  114. package/dist/response/ResponseHandler.mjs +1 -1
  115. package/dist/telemetry/BrowserPerformanceClient.mjs +1 -1
  116. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
  117. package/dist/utils/BrowserConstants.mjs +1 -1
  118. package/dist/utils/BrowserProtocolUtils.mjs +1 -1
  119. package/dist/utils/BrowserUtils.d.ts +3 -0
  120. package/dist/utils/BrowserUtils.d.ts.map +1 -1
  121. package/dist/utils/BrowserUtils.mjs +2 -1
  122. package/dist/utils/BrowserUtils.mjs.map +1 -1
  123. package/lib/msal-browser.cjs +10568 -10231
  124. package/lib/msal-browser.cjs.map +1 -1
  125. package/lib/msal-browser.js +10568 -10231
  126. package/lib/msal-browser.js.map +1 -1
  127. package/lib/msal-browser.min.js +69 -68
  128. package/package.json +6 -4
  129. package/src/app/IPublicClientApplication.ts +5 -0
  130. package/src/app/PublicClientApplication.ts +43 -8
  131. package/src/app/PublicClientNext.ts +3 -0
  132. package/src/cache/AccountManager.ts +184 -0
  133. package/src/cache/BrowserCacheManager.ts +11 -2
  134. package/src/config/Configuration.ts +3 -1
  135. package/src/controllers/ControllerFactory.ts +9 -14
  136. package/src/controllers/NestedAppAuthController.ts +375 -82
  137. package/src/controllers/StandardController.ts +125 -149
  138. package/src/index.ts +5 -1
  139. package/src/interaction_client/RedirectClient.ts +6 -12
  140. package/src/naa/BridgeAccountContext.ts +17 -0
  141. package/src/naa/BridgeCapabilities.ts +2 -1
  142. package/src/naa/BridgeProxy.ts +11 -6
  143. package/src/naa/BridgeRequestEnvelope.ts +1 -6
  144. package/src/naa/IBridgeProxy.ts +2 -2
  145. package/src/naa/InitContext.ts +2 -0
  146. package/src/naa/mapping/NestedAppAuthAdapter.ts +68 -2
  147. package/src/operatingcontext/{TeamsAppOperatingContext.ts → NestedAppOperatingContext.ts} +23 -31
  148. package/src/operatingcontext/StandardOperatingContext.ts +1 -0
  149. package/src/operatingcontext/UnknownOperatingContext.ts +8 -7
  150. package/src/packageMetadata.ts +1 -1
  151. package/src/utils/BrowserUtils.ts +4 -1
  152. package/dist/operatingcontext/TeamsAppOperatingContext.d.ts.map +0 -1
  153. package/dist/operatingcontext/TeamsAppOperatingContext.mjs.map +0 -1
@@ -13,8 +13,12 @@ import {
13
13
  IPerformanceClient,
14
14
  DEFAULT_CRYPTO_IMPLEMENTATION,
15
15
  PerformanceEvents,
16
- AccountFilter,
17
16
  TimeUtils,
17
+ buildStaticAuthorityOptions,
18
+ AccountEntity,
19
+ OIDC_DEFAULT_SCOPES,
20
+ BaseAuthRequest,
21
+ AccountFilter,
18
22
  } from "@azure/msal-common";
19
23
  import { ITokenCache } from "../cache/ITokenCache";
20
24
  import { BrowserConfiguration } from "../config/Configuration";
@@ -33,7 +37,7 @@ import {
33
37
  DEFAULT_REQUEST,
34
38
  } from "../utils/BrowserConstants";
35
39
  import { IController } from "./IController";
36
- import { TeamsAppOperatingContext } from "../operatingcontext/TeamsAppOperatingContext";
40
+ import { NestedAppOperatingContext } from "../operatingcontext/NestedAppOperatingContext";
37
41
  import { IBridgeProxy } from "../naa/IBridgeProxy";
38
42
  import { CryptoOps } from "../crypto/CryptoOps";
39
43
  import { NestedAppAuthAdapter } from "../naa/mapping/NestedAppAuthAdapter";
@@ -42,12 +46,16 @@ import { EventHandler } from "../event/EventHandler";
42
46
  import { EventType } from "../event/EventType";
43
47
  import { EventCallbackFunction, EventError } from "../event/EventMessage";
44
48
  import { AuthenticationResult } from "../response/AuthenticationResult";
45
- import { BrowserCacheManager } from "../cache/BrowserCacheManager";
49
+ import {
50
+ BrowserCacheManager,
51
+ DEFAULT_BROWSER_CACHE_MANAGER,
52
+ } from "../cache/BrowserCacheManager";
46
53
  import { ClearCacheRequest } from "../request/ClearCacheRequest";
54
+ import * as AccountManager from "../cache/AccountManager";
47
55
 
48
56
  export class NestedAppAuthController implements IController {
49
57
  // OperatingContext
50
- protected readonly operatingContext: TeamsAppOperatingContext;
58
+ protected readonly operatingContext: NestedAppOperatingContext;
51
59
 
52
60
  // BridgeProxy
53
61
  protected readonly bridgeProxy: IBridgeProxy;
@@ -58,6 +66,9 @@ export class NestedAppAuthController implements IController {
58
66
  // Input configuration by developer/user
59
67
  protected readonly config: BrowserConfiguration;
60
68
 
69
+ // Storage interface implementation
70
+ protected readonly browserStorage!: BrowserCacheManager;
71
+
61
72
  // Logger
62
73
  protected logger: Logger;
63
74
 
@@ -70,7 +81,7 @@ export class NestedAppAuthController implements IController {
70
81
  // NestedAppAuthAdapter
71
82
  protected readonly nestedAppAuthAdapter: NestedAppAuthAdapter;
72
83
 
73
- constructor(operatingContext: TeamsAppOperatingContext) {
84
+ constructor(operatingContext: NestedAppOperatingContext) {
74
85
  this.operatingContext = operatingContext;
75
86
  const proxy = this.operatingContext.getBridgeProxy();
76
87
  if (proxy !== undefined) {
@@ -84,6 +95,7 @@ export class NestedAppAuthController implements IController {
84
95
 
85
96
  // Initialize logger
86
97
  this.logger = this.operatingContext.getLogger();
98
+
87
99
  // Initialize performance client
88
100
  this.performanceClient = this.config.telemetry.client;
89
101
 
@@ -92,6 +104,20 @@ export class NestedAppAuthController implements IController {
92
104
  ? new CryptoOps(this.logger, this.performanceClient)
93
105
  : DEFAULT_CRYPTO_IMPLEMENTATION;
94
106
 
107
+ // Initialize the browser storage class.
108
+ this.browserStorage = this.operatingContext.isBrowserEnvironment()
109
+ ? new BrowserCacheManager(
110
+ this.config.auth.clientId,
111
+ this.config.cache,
112
+ this.browserCrypto,
113
+ this.logger,
114
+ buildStaticAuthorityOptions(this.config.auth)
115
+ )
116
+ : DEFAULT_BROWSER_CACHE_MANAGER(
117
+ this.config.auth.clientId,
118
+ this.logger
119
+ );
120
+
95
121
  this.eventHandler = new EventHandler(this.logger, this.browserCrypto);
96
122
 
97
123
  this.nestedAppAuthAdapter = new NestedAppAuthAdapter(
@@ -100,27 +126,54 @@ export class NestedAppAuthController implements IController {
100
126
  this.browserCrypto,
101
127
  this.logger
102
128
  );
103
- }
104
- getBrowserStorage(): BrowserCacheManager {
105
- throw NestedAppAuthError.createUnsupportedError();
129
+
130
+ // Set the active account if available
131
+ const accountContext = this.bridgeProxy.getAccountContext();
132
+ if (accountContext) {
133
+ const cachedAccount = AccountManager.getAccount(
134
+ accountContext,
135
+ this.logger,
136
+ this.browserStorage
137
+ );
138
+
139
+ AccountManager.setActiveAccount(cachedAccount, this.browserStorage);
140
+ }
106
141
  }
107
142
 
143
+ /**
144
+ * Returns the event handler instance
145
+ * @returns EventHandler
146
+ */
108
147
  getEventHandler(): EventHandler {
109
148
  return this.eventHandler;
110
149
  }
111
150
 
151
+ /**
152
+ * Factory function to create a new instance of NestedAppAuthController
153
+ * @param operatingContext
154
+ * @returns Promise<IController>
155
+ */
112
156
  static async createController(
113
- operatingContext: TeamsAppOperatingContext
157
+ operatingContext: NestedAppOperatingContext
114
158
  ): Promise<IController> {
115
159
  const controller = new NestedAppAuthController(operatingContext);
116
160
  return Promise.resolve(controller);
117
161
  }
118
162
 
163
+ /**
164
+ * Specific implementation of initialize function for NestedAppAuthController
165
+ * @returns
166
+ */
119
167
  initialize(): Promise<void> {
120
168
  // do nothing not required by this controller
121
169
  return Promise.resolve();
122
170
  }
123
171
 
172
+ /**
173
+ * Validate the incoming request and add correlationId if not present
174
+ * @param request
175
+ * @returns
176
+ */
124
177
  private ensureValidRequest<
125
178
  T extends
126
179
  | SsoSilentRequest
@@ -137,6 +190,11 @@ export class NestedAppAuthController implements IController {
137
190
  };
138
191
  }
139
192
 
193
+ /**
194
+ * Internal implementation of acquireTokenInteractive flow
195
+ * @param request
196
+ * @returns
197
+ */
140
198
  private async acquireTokenInteractive(
141
199
  request: PopupRequest | RedirectRequest
142
200
  ): Promise<AuthenticationResult> {
@@ -169,7 +227,10 @@ export class NestedAppAuthController implements IController {
169
227
  reqTimestamp
170
228
  );
171
229
 
172
- this.operatingContext.setActiveAccount(result.account);
230
+ // cache the tokens in the response
231
+ await this.hydrateCache(result, request);
232
+
233
+ this.browserStorage.setActiveAccount(result.account);
173
234
  this.eventHandler.emitEvent(
174
235
  EventType.ACQUIRE_TOKEN_SUCCESS,
175
236
  InteractionType.Popup,
@@ -207,6 +268,11 @@ export class NestedAppAuthController implements IController {
207
268
  }
208
269
  }
209
270
 
271
+ /**
272
+ * Internal implementation of acquireTokenSilent flow
273
+ * @param request
274
+ * @returns
275
+ */
210
276
  private async acquireTokenSilentInternal(
211
277
  request: SilentRequest
212
278
  ): Promise<AuthenticationResult> {
@@ -217,6 +283,19 @@ export class NestedAppAuthController implements IController {
217
283
  validRequest
218
284
  );
219
285
 
286
+ // Look for tokens in the cache first
287
+ const result = await this.acquireTokenFromCache(validRequest);
288
+
289
+ if (result) {
290
+ this.eventHandler.emitEvent(
291
+ EventType.ACQUIRE_TOKEN_SUCCESS,
292
+ InteractionType.Silent,
293
+ result
294
+ );
295
+ return result;
296
+ }
297
+
298
+ // proceed with acquiring tokens via the host
220
299
  const ssoSilentMeasurement = this.performanceClient.startMeasurement(
221
300
  PerformanceEvents.SsoSilent,
222
301
  validRequest.correlationId
@@ -243,7 +322,10 @@ export class NestedAppAuthController implements IController {
243
322
  reqTimestamp
244
323
  );
245
324
 
246
- this.operatingContext.setActiveAccount(result.account);
325
+ // cache the tokens in the response
326
+ await this.hydrateCache(result, request);
327
+
328
+ this.browserStorage.setActiveAccount(result.account);
247
329
  this.eventHandler.emitEvent(
248
330
  EventType.ACQUIRE_TOKEN_SUCCESS,
249
331
  InteractionType.Silent,
@@ -276,28 +358,201 @@ export class NestedAppAuthController implements IController {
276
358
  }
277
359
  }
278
360
 
361
+ /**
362
+ * acquires tokens from cache
363
+ * @param request
364
+ * @returns
365
+ */
366
+ private async acquireTokenFromCache(
367
+ request: SilentRequest
368
+ ): Promise<AuthenticationResult | null> {
369
+ const atsMeasurement = this.performanceClient.startMeasurement(
370
+ PerformanceEvents.AcquireTokenSilent,
371
+ request.correlationId
372
+ );
373
+
374
+ atsMeasurement?.add({
375
+ nestedAppAuthRequest: true,
376
+ });
377
+
378
+ const result = await this.acquireTokenFromCacheInternal(request);
379
+
380
+ if (result) {
381
+ this.eventHandler.emitEvent(
382
+ EventType.ACQUIRE_TOKEN_SUCCESS,
383
+ InteractionType.Silent,
384
+ result
385
+ );
386
+ atsMeasurement?.add({
387
+ accessTokenSize: result?.accessToken.length,
388
+ idTokenSize: result?.idToken.length,
389
+ });
390
+ atsMeasurement?.end({
391
+ success: true,
392
+ });
393
+ return result;
394
+ }
395
+
396
+ this.logger.error(
397
+ "Cached tokens are not found for the account, proceeding with silent token request."
398
+ );
399
+
400
+ this.eventHandler.emitEvent(
401
+ EventType.ACQUIRE_TOKEN_FAILURE,
402
+ InteractionType.Silent,
403
+ null
404
+ );
405
+ atsMeasurement?.end({
406
+ success: false,
407
+ });
408
+
409
+ return null;
410
+ }
411
+
412
+ /**
413
+ *
414
+ * @param request
415
+ * @returns
416
+ */
417
+ private async acquireTokenFromCacheInternal(
418
+ request: SilentRequest
419
+ ): Promise<AuthenticationResult | null> {
420
+ const accountContext = this.bridgeProxy.getAccountContext();
421
+ let currentAccount = null;
422
+ if (accountContext) {
423
+ const hubAccount = AccountManager.getAccount(
424
+ accountContext,
425
+ this.logger,
426
+ this.browserStorage
427
+ );
428
+ // always prioritize for hub account context, the reqirement of `request.account` will be removed soon
429
+ currentAccount = hubAccount || request.account;
430
+ }
431
+
432
+ // fall back to brokering if no cached account is found
433
+ if (!currentAccount) {
434
+ this.logger.verbose(
435
+ "No active account found, falling back to the host"
436
+ );
437
+ return Promise.resolve(null);
438
+ }
439
+
440
+ this.logger.verbose(
441
+ "active account found, attempting to acquire token silently"
442
+ );
443
+
444
+ const authRequest: BaseAuthRequest = {
445
+ ...request,
446
+ correlationId:
447
+ request.correlationId || this.browserCrypto.createNewGuid(),
448
+ authority: request.authority || currentAccount.environment,
449
+ scopes: request.scopes?.length
450
+ ? request.scopes
451
+ : [...OIDC_DEFAULT_SCOPES],
452
+ };
453
+
454
+ // fetch access token and check for expiry
455
+ const tokenKeys = this.browserStorage.getTokenKeys();
456
+ const cachedAccessToken = this.browserStorage.getAccessToken(
457
+ currentAccount,
458
+ authRequest,
459
+ tokenKeys,
460
+ currentAccount.tenantId,
461
+ this.performanceClient,
462
+ authRequest.correlationId
463
+ );
464
+
465
+ // If there is no access token, log it and return null
466
+ if (!cachedAccessToken) {
467
+ this.logger.verbose("No cached access token found");
468
+ return Promise.resolve(null);
469
+ // If access token has expired, remove the token from cache and return null
470
+ } else if (
471
+ TimeUtils.wasClockTurnedBack(cachedAccessToken.cachedAt) ||
472
+ TimeUtils.isTokenExpired(
473
+ cachedAccessToken.expiresOn,
474
+ this.config.system.tokenRenewalOffsetSeconds
475
+ )
476
+ ) {
477
+ this.logger.verbose(
478
+ "Cached access token has expired, deleting all related tokens from cache"
479
+ );
480
+ const accountEntity =
481
+ AccountEntity.createFromAccountInfo(currentAccount);
482
+ await this.browserStorage.removeAccountContext(accountEntity);
483
+ return Promise.resolve(null);
484
+ }
485
+
486
+ const cachedIdToken = this.browserStorage.getIdToken(
487
+ currentAccount,
488
+ tokenKeys,
489
+ currentAccount.tenantId,
490
+ this.performanceClient,
491
+ authRequest.correlationId
492
+ );
493
+
494
+ if (!cachedIdToken) {
495
+ this.logger.verbose("No cached id token found");
496
+ return Promise.resolve(null);
497
+ }
498
+
499
+ return this.nestedAppAuthAdapter.toAuthenticationResultFromCache(
500
+ currentAccount,
501
+ cachedIdToken,
502
+ cachedAccessToken,
503
+ authRequest,
504
+ authRequest.correlationId
505
+ );
506
+ }
507
+
508
+ /**
509
+ * acquireTokenPopup flow implementation
510
+ * @param request
511
+ * @returns
512
+ */
279
513
  async acquireTokenPopup(
280
514
  request: PopupRequest
281
515
  ): Promise<AuthenticationResult> {
282
516
  return this.acquireTokenInteractive(request);
283
517
  }
518
+
519
+ /**
520
+ * acquireTokenRedirect flow is not supported in nested app auth
521
+ * @param request
522
+ */
284
523
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
285
524
  acquireTokenRedirect(request: RedirectRequest): Promise<void> {
286
525
  throw NestedAppAuthError.createUnsupportedError();
287
526
  }
288
527
 
528
+ /**
529
+ * acquireTokenSilent flow implementation
530
+ * @param silentRequest
531
+ * @returns
532
+ */
289
533
  async acquireTokenSilent(
290
534
  silentRequest: SilentRequest
291
535
  ): Promise<AuthenticationResult> {
292
536
  return this.acquireTokenSilentInternal(silentRequest);
293
537
  }
294
538
 
539
+ /**
540
+ * Hybrid flow is not currently supported in nested app auth
541
+ * @param request
542
+ */
295
543
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
296
544
  acquireTokenByCode(
297
545
  request: AuthorizationCodeRequest // eslint-disable-line @typescript-eslint/no-unused-vars
298
546
  ): Promise<AuthenticationResult> {
299
547
  throw NestedAppAuthError.createUnsupportedError();
300
548
  }
549
+
550
+ /**
551
+ * acquireTokenNative flow is not currently supported in nested app auth
552
+ * @param request
553
+ * @param apiId
554
+ * @param accountId
555
+ */
301
556
  acquireTokenNative(
302
557
  request: // eslint-disable-line @typescript-eslint/no-unused-vars
303
558
  | SilentRequest
@@ -317,6 +572,12 @@ export class NestedAppAuthController implements IController {
317
572
  ): Promise<AuthenticationResult> {
318
573
  throw NestedAppAuthError.createUnsupportedError();
319
574
  }
575
+
576
+ /**
577
+ * acquireTokenByRefreshToken flow is not currently supported in nested app auth
578
+ * @param commonRequest
579
+ * @param silentRequest
580
+ */
320
581
  acquireTokenByRefreshToken(
321
582
  commonRequest: CommonSilentFlowRequest, // eslint-disable-line @typescript-eslint/no-unused-vars
322
583
  silentRequest: SilentRequest // eslint-disable-line @typescript-eslint/no-unused-vars
@@ -344,77 +605,116 @@ export class NestedAppAuthController implements IController {
344
605
  addPerformanceCallback(callback: PerformanceCallbackFunction): string {
345
606
  throw NestedAppAuthError.createUnsupportedError();
346
607
  }
608
+
347
609
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
348
610
  removePerformanceCallback(callbackId: string): boolean {
349
611
  throw NestedAppAuthError.createUnsupportedError();
350
612
  }
613
+
351
614
  enableAccountStorageEvents(): void {
352
615
  throw NestedAppAuthError.createUnsupportedError();
353
616
  }
617
+
354
618
  disableAccountStorageEvents(): void {
355
619
  throw NestedAppAuthError.createUnsupportedError();
356
620
  }
357
621
 
358
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
622
+ // #region Account APIs
623
+
624
+ /**
625
+ * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.
626
+ * @param accountFilter - (Optional) filter to narrow down the accounts returned
627
+ * @returns Array of AccountInfo objects in cache
628
+ */
629
+ getAllAccounts(accountFilter?: AccountFilter): AccountInfo[] {
630
+ return AccountManager.getAllAccounts(
631
+ this.logger,
632
+ this.browserStorage,
633
+ this.isBrowserEnv(),
634
+ accountFilter
635
+ );
636
+ }
637
+
638
+ /**
639
+ * Returns the first account found in the cache that matches the account filter passed in.
640
+ * @param accountFilter
641
+ * @returns The first account found in the cache matching the provided filter or null if no account could be found.
642
+ */
359
643
  getAccount(accountFilter: AccountFilter): AccountInfo | null {
360
- throw NestedAppAuthError.createUnsupportedError();
361
- // TODO: Look at standard implementation
644
+ return AccountManager.getAccount(
645
+ accountFilter,
646
+ this.logger,
647
+ this.browserStorage
648
+ );
649
+ }
650
+
651
+ /**
652
+ * Returns the signed in account matching username.
653
+ * (the account object is created at the time of successful login)
654
+ * or null when no matching account is found.
655
+ * This API is provided for convenience but getAccountById should be used for best reliability
656
+ * @param username
657
+ * @returns The account object stored in MSAL
658
+ */
659
+ getAccountByUsername(username: string): AccountInfo | null {
660
+ return AccountManager.getAccountByUsername(
661
+ username,
662
+ this.logger,
663
+ this.browserStorage
664
+ );
362
665
  }
363
666
 
667
+ /**
668
+ * Returns the signed in account matching homeAccountId.
669
+ * (the account object is created at the time of successful login)
670
+ * or null when no matching account is found
671
+ * @param homeAccountId
672
+ * @returns The account object stored in MSAL
673
+ */
364
674
  getAccountByHomeId(homeAccountId: string): AccountInfo | null {
365
- const currentAccount = this.operatingContext.getActiveAccount();
366
- if (currentAccount !== undefined) {
367
- if (currentAccount.homeAccountId === homeAccountId) {
368
- return this.nestedAppAuthAdapter.fromNaaAccountInfo(
369
- currentAccount
370
- );
371
- } else {
372
- return null;
373
- }
374
- } else {
375
- return null;
376
- }
675
+ return AccountManager.getAccountByHomeId(
676
+ homeAccountId,
677
+ this.logger,
678
+ this.browserStorage
679
+ );
377
680
  }
378
681
 
379
- getAccountByLocalId(localId: string): AccountInfo | null {
380
- const currentAccount = this.operatingContext.getActiveAccount();
381
- if (currentAccount !== undefined) {
382
- if (currentAccount.localAccountId === localId) {
383
- return this.nestedAppAuthAdapter.fromNaaAccountInfo(
384
- currentAccount
385
- );
386
- } else {
387
- return null;
388
- }
389
- } else {
390
- return null;
391
- }
682
+ /**
683
+ * Returns the signed in account matching localAccountId.
684
+ * (the account object is created at the time of successful login)
685
+ * or null when no matching account is found
686
+ * @param localAccountId
687
+ * @returns The account object stored in MSAL
688
+ */
689
+ getAccountByLocalId(localAccountId: string): AccountInfo | null {
690
+ return AccountManager.getAccountByLocalId(
691
+ localAccountId,
692
+ this.logger,
693
+ this.browserStorage
694
+ );
392
695
  }
393
696
 
394
- getAccountByUsername(userName: string): AccountInfo | null {
395
- const currentAccount = this.operatingContext.getActiveAccount();
396
- if (currentAccount !== undefined) {
397
- if (currentAccount.username === userName) {
398
- return this.nestedAppAuthAdapter.fromNaaAccountInfo(
399
- currentAccount
400
- );
401
- } else {
402
- return null;
403
- }
404
- } else {
405
- return null;
406
- }
697
+ /**
698
+ * Sets the account to use as the active account. If no account is passed to the acquireToken APIs, then MSAL will use this active account.
699
+ * @param account
700
+ */
701
+ setActiveAccount(account: AccountInfo | null): void {
702
+ /*
703
+ * StandardController uses this to allow the developer to set the active account
704
+ * in the nested app auth scenario the active account is controlled by the app hosting the nested app
705
+ */
706
+ return AccountManager.setActiveAccount(account, this.browserStorage);
407
707
  }
408
- getAllAccounts(): AccountInfo[] {
409
- const currentAccount = this.operatingContext.getActiveAccount();
410
- if (currentAccount !== undefined) {
411
- return [
412
- this.nestedAppAuthAdapter.fromNaaAccountInfo(currentAccount),
413
- ];
414
- } else {
415
- return [];
416
- }
708
+
709
+ /**
710
+ * Gets the currently active account
711
+ */
712
+ getActiveAccount(): AccountInfo | null {
713
+ return AccountManager.getActiveAccount(this.browserStorage);
417
714
  }
715
+
716
+ // #endregion
717
+
418
718
  handleRedirectPromise(
419
719
  hash?: string | undefined // eslint-disable-line @typescript-eslint/no-unused-vars
420
720
  ): Promise<AuthenticationResult | null> {
@@ -477,23 +777,6 @@ export class NestedAppAuthController implements IController {
477
777
  this.logger = logger;
478
778
  }
479
779
 
480
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
481
- setActiveAccount(account: AccountInfo | null): void {
482
- /*
483
- * StandardController uses this to allow the developer to set the active account
484
- * in the nested app auth scenario the active account is controlled by the app hosting the nested app
485
- */
486
- this.logger.warning("nestedAppAuth does not support setActiveAccount");
487
- return;
488
- }
489
- getActiveAccount(): AccountInfo | null {
490
- const currentAccount = this.operatingContext.getActiveAccount();
491
- if (currentAccount !== undefined) {
492
- return this.nestedAppAuthAdapter.fromNaaAccountInfo(currentAccount);
493
- } else {
494
- return null;
495
- }
496
- }
497
780
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
498
781
  initializeWrapperLibrary(sku: WrapperSKU, version: string): void {
499
782
  /*
@@ -502,21 +785,26 @@ export class NestedAppAuthController implements IController {
502
785
  */
503
786
  return;
504
787
  }
788
+
505
789
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
506
790
  setNavigationClient(navigationClient: INavigationClient): void {
507
791
  this.logger.warning(
508
792
  "setNavigationClient is not supported in nested app auth"
509
793
  );
510
794
  }
795
+
511
796
  getConfiguration(): BrowserConfiguration {
512
797
  return this.config;
513
798
  }
799
+
514
800
  isBrowserEnv(): boolean {
515
801
  return this.operatingContext.isBrowserEnvironment();
516
802
  }
803
+
517
804
  getBrowserCrypto(): ICrypto {
518
805
  return this.browserCrypto;
519
806
  }
807
+
520
808
  getPerformanceClient(): IPerformanceClient {
521
809
  throw NestedAppAuthError.createUnsupportedError();
522
810
  }
@@ -530,17 +818,22 @@ export class NestedAppAuthController implements IController {
530
818
  throw NestedAppAuthError.createUnsupportedError();
531
819
  }
532
820
 
533
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
534
821
  async hydrateCache(
535
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
536
822
  result: AuthenticationResult,
537
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
538
823
  request:
539
824
  | SilentRequest
540
825
  | SsoSilentRequest
541
826
  | RedirectRequest
542
827
  | PopupRequest
543
828
  ): Promise<void> {
544
- throw NestedAppAuthError.createUnsupportedError();
829
+ this.logger.verbose("hydrateCache called");
830
+
831
+ const accountEntity = AccountEntity.createFromAccountInfo(
832
+ result.account,
833
+ result.cloudGraphHostName,
834
+ result.msGraphHost
835
+ );
836
+ this.browserStorage.setAccount(accountEntity);
837
+ return this.browserStorage.hydrateCache(result, request);
545
838
  }
546
839
  }