@azure/msal-browser 3.15.0 → 3.17.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 (95) hide show
  1. package/dist/app/IPublicClientApplication.mjs +1 -1
  2. package/dist/app/PublicClientApplication.mjs +1 -1
  3. package/dist/app/PublicClientNext.mjs +1 -1
  4. package/dist/broker/nativeBroker/NativeMessageHandler.mjs +1 -1
  5. package/dist/broker/nativeBroker/NativeRequest.d.ts +1 -0
  6. package/dist/broker/nativeBroker/NativeRequest.d.ts.map +1 -1
  7. package/dist/broker/nativeBroker/NativeStatusCodes.mjs +1 -1
  8. package/dist/cache/AccountManager.mjs +1 -1
  9. package/dist/cache/AsyncMemoryStorage.mjs +1 -1
  10. package/dist/cache/BrowserCacheManager.mjs +1 -1
  11. package/dist/cache/BrowserStorage.mjs +1 -1
  12. package/dist/cache/DatabaseStorage.mjs +1 -1
  13. package/dist/cache/MemoryStorage.mjs +1 -1
  14. package/dist/cache/TokenCache.mjs +1 -1
  15. package/dist/config/Configuration.mjs +1 -1
  16. package/dist/controllers/ControllerFactory.mjs +1 -1
  17. package/dist/controllers/NestedAppAuthController.mjs +1 -1
  18. package/dist/controllers/StandardController.d.ts.map +1 -1
  19. package/dist/controllers/StandardController.mjs +58 -37
  20. package/dist/controllers/StandardController.mjs.map +1 -1
  21. package/dist/controllers/UnknownOperatingContextController.mjs +1 -1
  22. package/dist/crypto/BrowserCrypto.mjs +1 -1
  23. package/dist/crypto/CryptoOps.d.ts +11 -0
  24. package/dist/crypto/CryptoOps.d.ts.map +1 -1
  25. package/dist/crypto/CryptoOps.mjs +16 -1
  26. package/dist/crypto/CryptoOps.mjs.map +1 -1
  27. package/dist/crypto/PkceGenerator.mjs +1 -1
  28. package/dist/crypto/SignedHttpRequest.mjs +1 -1
  29. package/dist/encode/Base64Decode.mjs +1 -1
  30. package/dist/encode/Base64Encode.mjs +1 -1
  31. package/dist/error/BrowserAuthError.d.ts +5 -0
  32. package/dist/error/BrowserAuthError.d.ts.map +1 -1
  33. package/dist/error/BrowserAuthError.mjs +7 -2
  34. package/dist/error/BrowserAuthError.mjs.map +1 -1
  35. package/dist/error/BrowserAuthErrorCodes.d.ts +1 -0
  36. package/dist/error/BrowserAuthErrorCodes.d.ts.map +1 -1
  37. package/dist/error/BrowserAuthErrorCodes.mjs +3 -2
  38. package/dist/error/BrowserAuthErrorCodes.mjs.map +1 -1
  39. package/dist/error/BrowserConfigurationAuthError.mjs +1 -1
  40. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +1 -1
  41. package/dist/error/NativeAuthError.mjs +1 -1
  42. package/dist/error/NativeAuthErrorCodes.mjs +1 -1
  43. package/dist/error/NestedAppAuthError.mjs +1 -1
  44. package/dist/event/EventHandler.mjs +1 -1
  45. package/dist/event/EventMessage.mjs +1 -1
  46. package/dist/event/EventType.mjs +1 -1
  47. package/dist/index.mjs +1 -1
  48. package/dist/interaction_client/BaseInteractionClient.mjs +1 -1
  49. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
  50. package/dist/interaction_client/NativeInteractionClient.d.ts +4 -3
  51. package/dist/interaction_client/NativeInteractionClient.d.ts.map +1 -1
  52. package/dist/interaction_client/NativeInteractionClient.mjs +34 -14
  53. package/dist/interaction_client/NativeInteractionClient.mjs.map +1 -1
  54. package/dist/interaction_client/PopupClient.mjs +1 -1
  55. package/dist/interaction_client/RedirectClient.mjs +1 -1
  56. package/dist/interaction_client/SilentAuthCodeClient.mjs +1 -1
  57. package/dist/interaction_client/SilentCacheClient.mjs +1 -1
  58. package/dist/interaction_client/SilentIframeClient.mjs +1 -1
  59. package/dist/interaction_client/SilentRefreshClient.mjs +1 -1
  60. package/dist/interaction_client/StandardInteractionClient.mjs +1 -1
  61. package/dist/interaction_handler/InteractionHandler.mjs +1 -1
  62. package/dist/interaction_handler/RedirectHandler.mjs +1 -1
  63. package/dist/interaction_handler/SilentHandler.mjs +1 -1
  64. package/dist/naa/BridgeError.mjs +1 -1
  65. package/dist/naa/BridgeProxy.mjs +1 -1
  66. package/dist/naa/BridgeStatusCode.mjs +1 -1
  67. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +1 -1
  68. package/dist/navigation/NavigationClient.mjs +1 -1
  69. package/dist/network/FetchClient.mjs +1 -1
  70. package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
  71. package/dist/operatingcontext/NestedAppOperatingContext.mjs +1 -1
  72. package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
  73. package/dist/operatingcontext/UnknownOperatingContext.mjs +1 -1
  74. package/dist/packageMetadata.d.ts +1 -1
  75. package/dist/packageMetadata.mjs +2 -2
  76. package/dist/request/RequestHelpers.mjs +1 -1
  77. package/dist/response/ResponseHandler.mjs +1 -1
  78. package/dist/telemetry/BrowserPerformanceClient.mjs +1 -1
  79. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
  80. package/dist/utils/BrowserConstants.mjs +1 -1
  81. package/dist/utils/BrowserProtocolUtils.mjs +1 -1
  82. package/dist/utils/BrowserUtils.mjs +1 -1
  83. package/lib/msal-browser.cjs +229 -127
  84. package/lib/msal-browser.cjs.map +1 -1
  85. package/lib/msal-browser.js +229 -127
  86. package/lib/msal-browser.js.map +1 -1
  87. package/lib/msal-browser.min.js +61 -61
  88. package/package.json +2 -2
  89. package/src/broker/nativeBroker/NativeRequest.ts +1 -0
  90. package/src/controllers/StandardController.ts +89 -63
  91. package/src/crypto/CryptoOps.ts +17 -0
  92. package/src/error/BrowserAuthError.ts +8 -0
  93. package/src/error/BrowserAuthErrorCodes.ts +1 -0
  94. package/src/interaction_client/NativeInteractionClient.ts +55 -18
  95. package/src/packageMetadata.ts +1 -1
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "type": "git",
11
11
  "url": "https://github.com/AzureAD/microsoft-authentication-library-for-js.git"
12
12
  },
13
- "version": "3.15.0",
13
+ "version": "3.17.0",
14
14
  "description": "Microsoft Authentication Library for js",
15
15
  "keywords": [
16
16
  "implicit",
@@ -103,6 +103,6 @@
103
103
  "typescript": "^4.9.5"
104
104
  },
105
105
  "dependencies": {
106
- "@azure/msal-common": "14.10.0"
106
+ "@azure/msal-common": "14.12.0"
107
107
  }
108
108
  }
@@ -31,6 +31,7 @@ export type NativeTokenRequest = {
31
31
  extendedExpiryToken?: boolean;
32
32
  extraParameters?: StringDict;
33
33
  storeInCache?: StoreInCache; // Object of booleans indicating whether to store tokens in the cache or not (default is true)
34
+ signPopToken?: boolean; // Set to true only if token request deos not contain a PoP keyId
34
35
  };
35
36
 
36
37
  /**
@@ -422,7 +422,7 @@ export class StandardController implements IController {
422
422
  true
423
423
  ) || "";
424
424
  const rootMeasurement = this.performanceClient.startMeasurement(
425
- "acquireTokenRedirect",
425
+ PerformanceEvents.AcquireTokenRedirect,
426
426
  correlationId
427
427
  );
428
428
  this.eventHandler.emitEvent(
@@ -567,88 +567,114 @@ export class StandardController implements IController {
567
567
  // Preflight request
568
568
  const correlationId = this.getRequestCorrelationId(request);
569
569
  this.logger.verbose("acquireTokenRedirect called", correlationId);
570
- BrowserUtils.redirectPreflightCheck(this.initialized, this.config);
571
- this.browserStorage.setInteractionInProgress(true);
570
+
571
+ const atrMeasurement = this.performanceClient.startMeasurement(
572
+ PerformanceEvents.AcquireTokenPreRedirect,
573
+ correlationId
574
+ );
575
+ atrMeasurement.add({
576
+ accountType: getAccountType(request.account),
577
+ scenarioId: request.scenarioId,
578
+ });
579
+
580
+ const onRedirectNavigateCb = request.onRedirectNavigate;
581
+ request.onRedirectNavigate = (url: string) => {
582
+ const navigate =
583
+ typeof onRedirectNavigateCb === "function"
584
+ ? onRedirectNavigateCb(url)
585
+ : undefined;
586
+ if (navigate !== false) {
587
+ atrMeasurement.end({ success: true });
588
+ } else {
589
+ atrMeasurement.discard();
590
+ }
591
+ return navigate;
592
+ };
572
593
 
573
594
  // If logged in, emit acquire token events
574
595
  const isLoggedIn = this.getAllAccounts().length > 0;
575
- if (isLoggedIn) {
576
- this.eventHandler.emitEvent(
577
- EventType.ACQUIRE_TOKEN_START,
578
- InteractionType.Redirect,
579
- request
580
- );
581
- } else {
582
- this.eventHandler.emitEvent(
583
- EventType.LOGIN_START,
584
- InteractionType.Redirect,
585
- request
586
- );
587
- }
596
+ try {
597
+ BrowserUtils.redirectPreflightCheck(this.initialized, this.config);
598
+ this.browserStorage.setInteractionInProgress(true);
588
599
 
589
- let result: Promise<void>;
600
+ if (isLoggedIn) {
601
+ this.eventHandler.emitEvent(
602
+ EventType.ACQUIRE_TOKEN_START,
603
+ InteractionType.Redirect,
604
+ request
605
+ );
606
+ } else {
607
+ this.eventHandler.emitEvent(
608
+ EventType.LOGIN_START,
609
+ InteractionType.Redirect,
610
+ request
611
+ );
612
+ }
590
613
 
591
- if (this.nativeExtensionProvider && this.canUseNative(request)) {
592
- const nativeClient = new NativeInteractionClient(
593
- this.config,
594
- this.browserStorage,
595
- this.browserCrypto,
596
- this.logger,
597
- this.eventHandler,
598
- this.navigationClient,
599
- ApiId.acquireTokenRedirect,
600
- this.performanceClient,
601
- this.nativeExtensionProvider,
602
- this.getNativeAccountId(request),
603
- this.nativeInternalStorage,
604
- correlationId
605
- );
606
- result = nativeClient
607
- .acquireTokenRedirect(request)
608
- .catch((e: AuthError) => {
609
- if (
610
- e instanceof NativeAuthError &&
611
- isFatalNativeAuthError(e)
612
- ) {
613
- this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
614
- const redirectClient =
615
- this.createRedirectClient(correlationId);
616
- return redirectClient.acquireToken(request);
617
- } else if (e instanceof InteractionRequiredAuthError) {
618
- this.logger.verbose(
619
- "acquireTokenRedirect - Resolving interaction required error thrown by native broker by falling back to web flow"
620
- );
621
- const redirectClient =
622
- this.createRedirectClient(correlationId);
623
- return redirectClient.acquireToken(request);
624
- }
625
- this.browserStorage.setInteractionInProgress(false);
626
- throw e;
627
- });
628
- } else {
629
- const redirectClient = this.createRedirectClient(correlationId);
630
- result = redirectClient.acquireToken(request);
631
- }
614
+ let result: Promise<void>;
632
615
 
633
- return result.catch((e) => {
634
- // If logged in, emit acquire token events
616
+ if (this.nativeExtensionProvider && this.canUseNative(request)) {
617
+ const nativeClient = new NativeInteractionClient(
618
+ this.config,
619
+ this.browserStorage,
620
+ this.browserCrypto,
621
+ this.logger,
622
+ this.eventHandler,
623
+ this.navigationClient,
624
+ ApiId.acquireTokenRedirect,
625
+ this.performanceClient,
626
+ this.nativeExtensionProvider,
627
+ this.getNativeAccountId(request),
628
+ this.nativeInternalStorage,
629
+ correlationId
630
+ );
631
+ result = nativeClient
632
+ .acquireTokenRedirect(request, atrMeasurement)
633
+ .catch((e: AuthError) => {
634
+ if (
635
+ e instanceof NativeAuthError &&
636
+ isFatalNativeAuthError(e)
637
+ ) {
638
+ this.nativeExtensionProvider = undefined; // If extension gets uninstalled during session prevent future requests from continuing to attempt
639
+ const redirectClient =
640
+ this.createRedirectClient(correlationId);
641
+ return redirectClient.acquireToken(request);
642
+ } else if (e instanceof InteractionRequiredAuthError) {
643
+ this.logger.verbose(
644
+ "acquireTokenRedirect - Resolving interaction required error thrown by native broker by falling back to web flow"
645
+ );
646
+ const redirectClient =
647
+ this.createRedirectClient(correlationId);
648
+ return redirectClient.acquireToken(request);
649
+ }
650
+ this.browserStorage.setInteractionInProgress(false);
651
+ throw e;
652
+ });
653
+ } else {
654
+ const redirectClient = this.createRedirectClient(correlationId);
655
+ result = redirectClient.acquireToken(request);
656
+ }
657
+
658
+ return await result;
659
+ } catch (e) {
660
+ atrMeasurement.end({ success: false }, e);
635
661
  if (isLoggedIn) {
636
662
  this.eventHandler.emitEvent(
637
663
  EventType.ACQUIRE_TOKEN_FAILURE,
638
664
  InteractionType.Redirect,
639
665
  null,
640
- e
666
+ e as EventError
641
667
  );
642
668
  } else {
643
669
  this.eventHandler.emitEvent(
644
670
  EventType.LOGIN_FAILURE,
645
671
  InteractionType.Redirect,
646
672
  null,
647
- e
673
+ e as EventError
648
674
  );
649
675
  }
650
676
  throw e;
651
- });
677
+ }
652
678
  }
653
679
 
654
680
  // #endregion
@@ -78,6 +78,23 @@ export class CryptoOps implements ICrypto {
78
78
  return base64Decode(input);
79
79
  }
80
80
 
81
+ /**
82
+ * Encodes input string to base64 URL safe string.
83
+ * @param input
84
+ */
85
+ base64UrlEncode(input: string): string {
86
+ return urlEncode(input);
87
+ }
88
+
89
+ /**
90
+ * Stringifies and base64Url encodes input public key
91
+ * @param inputKid
92
+ * @returns Base64Url encoded public key
93
+ */
94
+ encodeKid(inputKid: string): string {
95
+ return this.base64UrlEncode(JSON.stringify({ kid: inputKid }));
96
+ }
97
+
81
98
  /**
82
99
  * Generates a keypair, stores it and returns a thumbprint
83
100
  * @param request
@@ -90,6 +90,8 @@ export const BrowserAuthErrorMessages = {
90
90
  "The provided prompt is not supported by the native platform. This request should be routed to the web based flow.",
91
91
  [BrowserAuthErrorCodes.invalidBase64String]:
92
92
  "Invalid base64 encoded string.",
93
+ [BrowserAuthErrorCodes.invalidPopTokenRequest]:
94
+ "Invalid PoP token request. The request should not have both a popKid value and signPopToken set to true.",
93
95
  };
94
96
 
95
97
  /**
@@ -333,6 +335,12 @@ export const BrowserAuthErrorMessage = {
333
335
  BrowserAuthErrorCodes.invalidBase64String
334
336
  ],
335
337
  },
338
+ invalidPopTokenRequest: {
339
+ code: BrowserAuthErrorCodes.invalidPopTokenRequest,
340
+ desc: BrowserAuthErrorMessages[
341
+ BrowserAuthErrorCodes.invalidPopTokenRequest
342
+ ],
343
+ },
336
344
  };
337
345
 
338
346
  /**
@@ -55,3 +55,4 @@ export const uninitializedPublicClientApplication =
55
55
  "uninitialized_public_client_application";
56
56
  export const nativePromptNotSupported = "native_prompt_not_supported";
57
57
  export const invalidBase64String = "invalid_base64_string";
58
+ export const invalidPopTokenRequest = "invalid_pop_token_request";
@@ -36,6 +36,7 @@ import {
36
36
  updateAccountTenantProfileData,
37
37
  CacheHelpers,
38
38
  buildAccountToCache,
39
+ InProgressPerformanceEvent,
39
40
  } from "@azure/msal-common";
40
41
  import { BaseInteractionClient } from "./BaseInteractionClient";
41
42
  import { BrowserConfiguration } from "../config/Configuration";
@@ -169,10 +170,12 @@ export class NativeInteractionClient extends BaseInteractionClient {
169
170
  );
170
171
  }
171
172
 
173
+ const { ...nativeTokenRequest } = nativeRequest;
174
+
172
175
  // fall back to native calls
173
176
  const messageBody: NativeExtensionRequestBody = {
174
177
  method: NativeExtensionMethod.GetToken,
175
- request: nativeRequest,
178
+ request: nativeTokenRequest,
176
179
  };
177
180
 
178
181
  const response: object = await this.nativeMessageHandler.sendMessage(
@@ -276,17 +279,23 @@ export class NativeInteractionClient extends BaseInteractionClient {
276
279
 
277
280
  /**
278
281
  * Acquires a token from native platform then redirects to the redirectUri instead of returning the response
279
- * @param request
282
+ * @param {RedirectRequest} request
283
+ * @param {InProgressPerformanceEvent} rootMeasurement
280
284
  */
281
- async acquireTokenRedirect(request: RedirectRequest): Promise<void> {
285
+ async acquireTokenRedirect(
286
+ request: RedirectRequest,
287
+ rootMeasurement: InProgressPerformanceEvent
288
+ ): Promise<void> {
282
289
  this.logger.trace(
283
290
  "NativeInteractionClient - acquireTokenRedirect called."
284
291
  );
285
292
  const nativeRequest = await this.initializeNativeRequest(request);
286
293
 
294
+ const { ...nativeTokenRequest } = nativeRequest;
295
+
287
296
  const messageBody: NativeExtensionRequestBody = {
288
297
  method: NativeExtensionMethod.GetToken,
289
- request: nativeRequest,
298
+ request: nativeTokenRequest,
290
299
  };
291
300
 
292
301
  try {
@@ -313,6 +322,7 @@ export class NativeInteractionClient extends BaseInteractionClient {
313
322
  const redirectUri = this.config.auth.navigateToLoginRequestUrl
314
323
  ? window.location.href
315
324
  : this.getRedirectUri(request.redirectUri);
325
+ rootMeasurement.end({ success: true });
316
326
  await this.navigationClient.navigateExternal(
317
327
  redirectUri,
318
328
  navigationOptions
@@ -475,7 +485,7 @@ export class NativeInteractionClient extends BaseInteractionClient {
475
485
  request,
476
486
  homeAccountIdentifier,
477
487
  idTokenClaims,
478
- result.accessToken,
488
+ response.access_token,
479
489
  result.tenantId,
480
490
  reqTimestamp
481
491
  );
@@ -529,7 +539,10 @@ export class NativeInteractionClient extends BaseInteractionClient {
529
539
  response: NativeResponse,
530
540
  request: NativeTokenRequest
531
541
  ): Promise<string> {
532
- if (request.tokenType === AuthenticationScheme.POP) {
542
+ if (
543
+ request.tokenType === AuthenticationScheme.POP &&
544
+ request.signPopToken
545
+ ) {
533
546
  /**
534
547
  * This code prioritizes SHR returned from the native layer. In case of error/SHR not calculated from WAM and the AT
535
548
  * is still received, SHR is calculated locally
@@ -719,7 +732,11 @@ export class NativeInteractionClient extends BaseInteractionClient {
719
732
  responseScopes.printScopes(),
720
733
  tokenExpirationSeconds,
721
734
  0,
722
- base64Decode
735
+ base64Decode,
736
+ undefined,
737
+ request.tokenType as AuthenticationScheme,
738
+ undefined,
739
+ request.keyId
723
740
  );
724
741
 
725
742
  const nativeCacheRecord = new CacheRecord(
@@ -911,8 +928,16 @@ export class NativeInteractionClient extends BaseInteractionClient {
911
928
  ...request.tokenQueryParameters,
912
929
  },
913
930
  extendedExpiryToken: false, // Make this configurable?
931
+ keyId: request.popKid,
914
932
  };
915
933
 
934
+ // Check for PoP token requests: signPopToken should only be set to true if popKid is not set
935
+ if (validatedRequest.signPopToken && !!request.popKid) {
936
+ throw createBrowserAuthError(
937
+ BrowserAuthErrorCodes.invalidPopTokenRequest
938
+ );
939
+ }
940
+
916
941
  this.handleExtraBrokerParams(validatedRequest);
917
942
  validatedRequest.extraParameters =
918
943
  validatedRequest.extraParameters || {};
@@ -929,17 +954,29 @@ export class NativeInteractionClient extends BaseInteractionClient {
929
954
  };
930
955
 
931
956
  const popTokenGenerator = new PopTokenGenerator(this.browserCrypto);
932
- const reqCnfData = await invokeAsync(
933
- popTokenGenerator.generateCnf.bind(popTokenGenerator),
934
- PerformanceEvents.PopTokenGenerateCnf,
935
- this.logger,
936
- this.performanceClient,
937
- this.correlationId
938
- )(shrParameters, this.logger);
939
-
940
- // to reduce the URL length, it is recommended to send the hash of the req_cnf instead of the whole string
941
- validatedRequest.reqCnf = reqCnfData.reqCnfHash;
942
- validatedRequest.keyId = reqCnfData.kid;
957
+
958
+ // generate reqCnf if not provided in the request
959
+ let reqCnfData;
960
+ if (!validatedRequest.keyId) {
961
+ const generatedReqCnfData = await invokeAsync(
962
+ popTokenGenerator.generateCnf.bind(popTokenGenerator),
963
+ PerformanceEvents.PopTokenGenerateCnf,
964
+ this.logger,
965
+ this.performanceClient,
966
+ request.correlationId
967
+ )(shrParameters, this.logger);
968
+ reqCnfData = generatedReqCnfData.reqCnfString;
969
+ validatedRequest.keyId = generatedReqCnfData.kid;
970
+ validatedRequest.signPopToken = true;
971
+ } else {
972
+ reqCnfData = this.browserCrypto.base64UrlEncode(
973
+ JSON.stringify({ kid: validatedRequest.keyId })
974
+ );
975
+ validatedRequest.signPopToken = false;
976
+ }
977
+
978
+ // SPAs require whole string to be passed to broker
979
+ validatedRequest.reqCnf = reqCnfData;
943
980
  }
944
981
 
945
982
  return validatedRequest;
@@ -1,3 +1,3 @@
1
1
  /* eslint-disable header/header */
2
2
  export const name = "@azure/msal-browser";
3
- export const version = "3.15.0";
3
+ export const version = "3.17.0";