@azure/msal-browser 3.4.0 → 3.5.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 (124) 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/NativeStatusCodes.mjs +1 -1
  6. package/dist/cache/AsyncMemoryStorage.mjs +1 -1
  7. package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
  8. package/dist/cache/BrowserCacheManager.mjs +8 -8
  9. package/dist/cache/BrowserCacheManager.mjs.map +1 -1
  10. package/dist/cache/BrowserStorage.mjs +1 -1
  11. package/dist/cache/CryptoKeyStore.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 +23 -22
  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 +2 -2
  24. package/dist/crypto/CryptoOps.d.ts.map +1 -1
  25. package/dist/crypto/CryptoOps.mjs +4 -3
  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.mjs +1 -1
  32. package/dist/error/BrowserAuthErrorCodes.mjs +1 -1
  33. package/dist/error/BrowserConfigurationAuthError.mjs +1 -1
  34. package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +1 -1
  35. package/dist/error/NativeAuthError.mjs +1 -1
  36. package/dist/error/NativeAuthErrorCodes.mjs +1 -1
  37. package/dist/error/NestedAppAuthError.mjs +1 -1
  38. package/dist/event/EventHandler.mjs +1 -1
  39. package/dist/event/EventMessage.mjs +1 -1
  40. package/dist/event/EventType.mjs +1 -1
  41. package/dist/index.d.ts +1 -1
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.mjs +2 -2
  44. package/dist/interaction_client/BaseInteractionClient.d.ts +0 -1
  45. package/dist/interaction_client/BaseInteractionClient.d.ts.map +1 -1
  46. package/dist/interaction_client/BaseInteractionClient.mjs +2 -3
  47. package/dist/interaction_client/BaseInteractionClient.mjs.map +1 -1
  48. package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
  49. package/dist/interaction_client/NativeInteractionClient.mjs +1 -1
  50. package/dist/interaction_client/PopupClient.d.ts +0 -10
  51. package/dist/interaction_client/PopupClient.d.ts.map +1 -1
  52. package/dist/interaction_client/PopupClient.mjs +22 -92
  53. package/dist/interaction_client/PopupClient.mjs.map +1 -1
  54. package/dist/interaction_client/RedirectClient.d.ts +3 -3
  55. package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
  56. package/dist/interaction_client/RedirectClient.mjs +51 -34
  57. package/dist/interaction_client/RedirectClient.mjs.map +1 -1
  58. package/dist/interaction_client/SilentAuthCodeClient.mjs +1 -1
  59. package/dist/interaction_client/SilentCacheClient.mjs +1 -1
  60. package/dist/interaction_client/SilentIframeClient.d.ts.map +1 -1
  61. package/dist/interaction_client/SilentIframeClient.mjs +8 -17
  62. package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
  63. package/dist/interaction_client/SilentRefreshClient.mjs +1 -1
  64. package/dist/interaction_client/StandardInteractionClient.d.ts +1 -6
  65. package/dist/interaction_client/StandardInteractionClient.d.ts.map +1 -1
  66. package/dist/interaction_client/StandardInteractionClient.mjs +2 -24
  67. package/dist/interaction_client/StandardInteractionClient.mjs.map +1 -1
  68. package/dist/interaction_handler/InteractionHandler.d.ts +2 -2
  69. package/dist/interaction_handler/InteractionHandler.d.ts.map +1 -1
  70. package/dist/interaction_handler/InteractionHandler.mjs +5 -9
  71. package/dist/interaction_handler/InteractionHandler.mjs.map +1 -1
  72. package/dist/interaction_handler/RedirectHandler.d.ts +2 -2
  73. package/dist/interaction_handler/RedirectHandler.d.ts.map +1 -1
  74. package/dist/interaction_handler/RedirectHandler.mjs +4 -8
  75. package/dist/interaction_handler/RedirectHandler.mjs.map +1 -1
  76. package/dist/interaction_handler/SilentHandler.d.ts +2 -2
  77. package/dist/interaction_handler/SilentHandler.d.ts.map +1 -1
  78. package/dist/interaction_handler/SilentHandler.mjs +13 -7
  79. package/dist/interaction_handler/SilentHandler.mjs.map +1 -1
  80. package/dist/naa/BridgeError.mjs +1 -1
  81. package/dist/naa/BridgeProxy.mjs +1 -1
  82. package/dist/naa/BridgeStatusCode.mjs +1 -1
  83. package/dist/naa/mapping/NestedAppAuthAdapter.mjs +1 -1
  84. package/dist/navigation/NavigationClient.mjs +1 -1
  85. package/dist/network/FetchClient.mjs +1 -1
  86. package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
  87. package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
  88. package/dist/operatingcontext/TeamsAppOperatingContext.mjs +1 -1
  89. package/dist/operatingcontext/UnknownOperatingContext.mjs +1 -1
  90. package/dist/packageMetadata.d.ts +1 -1
  91. package/dist/packageMetadata.mjs +2 -2
  92. package/dist/response/ResponseHandler.d.ts +8 -0
  93. package/dist/response/ResponseHandler.d.ts.map +1 -0
  94. package/dist/response/ResponseHandler.mjs +46 -0
  95. package/dist/response/ResponseHandler.mjs.map +1 -0
  96. package/dist/telemetry/BrowserPerformanceClient.mjs +1 -1
  97. package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
  98. package/dist/utils/BrowserConstants.mjs +1 -1
  99. package/dist/utils/BrowserProtocolUtils.d.ts +7 -14
  100. package/dist/utils/BrowserProtocolUtils.d.ts.map +1 -1
  101. package/dist/utils/BrowserProtocolUtils.mjs +17 -30
  102. package/dist/utils/BrowserProtocolUtils.mjs.map +1 -1
  103. package/dist/utils/BrowserUtils.mjs +1 -1
  104. package/lib/msal-browser.cjs +360 -490
  105. package/lib/msal-browser.cjs.map +1 -1
  106. package/lib/msal-browser.js +360 -490
  107. package/lib/msal-browser.js.map +1 -1
  108. package/lib/msal-browser.min.js +66 -65
  109. package/package.json +2 -2
  110. package/src/cache/BrowserCacheManager.ts +7 -10
  111. package/src/controllers/StandardController.ts +28 -39
  112. package/src/crypto/CryptoOps.ts +5 -3
  113. package/src/index.ts +1 -0
  114. package/src/interaction_client/BaseInteractionClient.ts +1 -2
  115. package/src/interaction_client/PopupClient.ts +34 -137
  116. package/src/interaction_client/RedirectClient.ts +71 -55
  117. package/src/interaction_client/SilentIframeClient.ts +16 -27
  118. package/src/interaction_client/StandardInteractionClient.ts +2 -48
  119. package/src/interaction_handler/InteractionHandler.ts +5 -8
  120. package/src/interaction_handler/RedirectHandler.ts +4 -8
  121. package/src/interaction_handler/SilentHandler.ts +12 -5
  122. package/src/packageMetadata.ts +1 -1
  123. package/src/response/ResponseHandler.ts +73 -0
  124. package/src/utils/BrowserProtocolUtils.ts +17 -36
@@ -19,6 +19,8 @@ import {
19
19
  PerformanceEvents,
20
20
  ProtocolMode,
21
21
  invokeAsync,
22
+ ServerResponseType,
23
+ UrlUtils,
22
24
  } from "@azure/msal-common";
23
25
  import { StandardInteractionClient } from "./StandardInteractionClient";
24
26
  import {
@@ -44,6 +46,7 @@ import { EventHandler } from "../event/EventHandler";
44
46
  import { INavigationClient } from "../navigation/INavigationClient";
45
47
  import { EventError } from "../event/EventMessage";
46
48
  import { AuthenticationResult } from "../response/AuthenticationResult";
49
+ import * as ResponseHandler from "../response/ResponseHandler";
47
50
 
48
51
  export class RedirectClient extends StandardInteractionClient {
49
52
  protected nativeStorage: BrowserCacheManager;
@@ -201,33 +204,13 @@ export class RedirectClient extends StandardInteractionClient {
201
204
  );
202
205
  return null;
203
206
  }
204
- const responseHash = this.getRedirectResponseHash(
205
- hash || window.location.hash
207
+ const [serverParams, responseString] = this.getRedirectResponse(
208
+ hash || ""
206
209
  );
207
- if (!responseHash) {
210
+ if (!serverParams) {
208
211
  // Not a recognized server response hash or hash not associated with a redirect request
209
212
  this.logger.info(
210
- "handleRedirectPromise did not detect a response hash as a result of a redirect. Cleaning temporary cache."
211
- );
212
- this.browserStorage.cleanRequestByInteractionType(
213
- InteractionType.Redirect
214
- );
215
- return null;
216
- }
217
-
218
- let state: string;
219
- try {
220
- // Deserialize hash fragment response parameters.
221
- const serverParams: ServerAuthorizationCodeResponse =
222
- UrlString.getDeserializedHash(responseHash);
223
- state = this.validateAndExtractStateFromHash(
224
- serverParams,
225
- InteractionType.Redirect
226
- );
227
- this.logger.verbose("State extracted from hash");
228
- } catch (e) {
229
- this.logger.info(
230
- `handleRedirectPromise was unable to extract state due to: ${e}`
213
+ "handleRedirectPromise did not detect a response as a result of a redirect. Cleaning temporary cache."
231
214
  );
232
215
  this.browserStorage.cleanRequestByInteractionType(
233
216
  InteractionType.Redirect
@@ -253,12 +236,7 @@ export class RedirectClient extends StandardInteractionClient {
253
236
  ) {
254
237
  // We are on the page we need to navigate to - handle hash
255
238
  this.logger.verbose(
256
- "Current page is loginRequestUrl, handling hash"
257
- );
258
- const handleHashResult = await this.handleHash(
259
- responseHash,
260
- state,
261
- serverTelemetryManager
239
+ "Current page is loginRequestUrl, handling response"
262
240
  );
263
241
 
264
242
  if (loginRequestUrl.indexOf("#") > -1) {
@@ -266,14 +244,18 @@ export class RedirectClient extends StandardInteractionClient {
266
244
  BrowserUtils.replaceHash(loginRequestUrl);
267
245
  }
268
246
 
247
+ const handleHashResult = await this.handleResponse(
248
+ serverParams,
249
+ serverTelemetryManager
250
+ );
251
+
269
252
  return handleHashResult;
270
253
  } else if (!this.config.auth.navigateToLoginRequestUrl) {
271
254
  this.logger.verbose(
272
- "NavigateToLoginRequestUrl set to false, handling hash"
255
+ "NavigateToLoginRequestUrl set to false, handling response"
273
256
  );
274
- return this.handleHash(
275
- responseHash,
276
- state,
257
+ return this.handleResponse(
258
+ serverParams,
277
259
  serverTelemetryManager
278
260
  );
279
261
  } else if (
@@ -286,7 +268,7 @@ export class RedirectClient extends StandardInteractionClient {
286
268
  */
287
269
  this.browserStorage.setTemporaryCache(
288
270
  TemporaryCacheKeys.URL_HASH,
289
- responseHash,
271
+ responseString,
290
272
  true
291
273
  );
292
274
  const navigationOptions: NavigationOptions = {
@@ -331,9 +313,8 @@ export class RedirectClient extends StandardInteractionClient {
331
313
 
332
314
  // If navigateInternal implementation returns false, handle the hash now
333
315
  if (!processHashOnRedirect) {
334
- return this.handleHash(
335
- responseHash,
336
- state,
316
+ return this.handleResponse(
317
+ serverParams,
337
318
  serverTelemetryManager
338
319
  );
339
320
  }
@@ -357,18 +338,45 @@ export class RedirectClient extends StandardInteractionClient {
357
338
  * Returns null if interactionType in the state value is not "redirect" or the hash does not contain known properties
358
339
  * @param hash
359
340
  */
360
- protected getRedirectResponseHash(hash: string): string | null {
341
+ protected getRedirectResponse(
342
+ userProvidedResponse: string
343
+ ): [ServerAuthorizationCodeResponse | null, string] {
361
344
  this.logger.verbose("getRedirectResponseHash called");
362
345
  // Get current location hash from window or cache.
363
- const isResponseHash: boolean =
364
- UrlString.hashContainsKnownProperties(hash);
346
+ let responseString = userProvidedResponse;
347
+ if (!responseString) {
348
+ if (
349
+ this.config.auth.OIDCOptions.serverResponseType ===
350
+ ServerResponseType.QUERY
351
+ ) {
352
+ responseString = window.location.search;
353
+ } else {
354
+ responseString = window.location.hash;
355
+ }
356
+ }
357
+ let response = UrlUtils.getDeserializedResponse(responseString);
358
+
359
+ if (response) {
360
+ try {
361
+ ResponseHandler.validateInteractionType(
362
+ response,
363
+ this.browserCrypto,
364
+ InteractionType.Redirect
365
+ );
366
+ } catch (e) {
367
+ if (e instanceof AuthError) {
368
+ this.logger.error(
369
+ `Interaction type validation failed due to ${e.errorCode}: ${e.errorMessage}`
370
+ );
371
+ }
372
+ return [null, ""];
373
+ }
365
374
 
366
- if (isResponseHash) {
367
375
  BrowserUtils.clearHash(window);
368
376
  this.logger.verbose(
369
377
  "Hash contains known properties, returning response hash"
370
378
  );
371
- return hash;
379
+ return [response, responseString];
372
380
  }
373
381
 
374
382
  const cachedHash = this.browserStorage.getTemporaryCache(
@@ -379,10 +387,17 @@ export class RedirectClient extends StandardInteractionClient {
379
387
  this.browserStorage.generateCacheKey(TemporaryCacheKeys.URL_HASH)
380
388
  );
381
389
 
382
- this.logger.verbose(
383
- "Hash does not contain known properties, returning cached hash"
384
- );
385
- return cachedHash;
390
+ if (cachedHash) {
391
+ response = UrlUtils.getDeserializedResponse(cachedHash);
392
+ if (response) {
393
+ this.logger.verbose(
394
+ "Hash does not contain known properties, returning cached hash"
395
+ );
396
+ return [response, cachedHash];
397
+ }
398
+ }
399
+
400
+ return [null, ""];
386
401
  }
387
402
 
388
403
  /**
@@ -390,16 +405,17 @@ export class RedirectClient extends StandardInteractionClient {
390
405
  * @param hash
391
406
  * @param state
392
407
  */
393
- protected async handleHash(
394
- hash: string,
395
- state: string,
408
+ protected async handleResponse(
409
+ serverParams: ServerAuthorizationCodeResponse,
396
410
  serverTelemetryManager: ServerTelemetryManager
397
411
  ): Promise<AuthenticationResult> {
398
- const cachedRequest = this.browserStorage.getCachedRequest(state);
399
- this.logger.verbose("handleHash called, retrieved cached request");
412
+ const state = serverParams.state;
413
+ if (!state) {
414
+ throw createBrowserAuthError(BrowserAuthErrorCodes.noStateInHash);
415
+ }
400
416
 
401
- const serverParams: ServerAuthorizationCodeResponse =
402
- UrlString.getDeserializedHash(hash);
417
+ const cachedRequest = this.browserStorage.getCachedRequest(state);
418
+ this.logger.verbose("handleResponse called, retrieved cached request");
403
419
 
404
420
  if (serverParams.accountId) {
405
421
  this.logger.verbose(
@@ -467,7 +483,7 @@ export class RedirectClient extends StandardInteractionClient {
467
483
  this.logger,
468
484
  this.performanceClient
469
485
  );
470
- return await interactionHandler.handleCodeResponseFromHash(hash, state);
486
+ return await interactionHandler.handleCodeResponse(serverParams, state);
471
487
  }
472
488
 
473
489
  /**
@@ -10,12 +10,11 @@ import {
10
10
  CommonAuthorizationCodeRequest,
11
11
  AuthorizationCodeClient,
12
12
  AuthError,
13
- UrlString,
14
- ServerAuthorizationCodeResponse,
15
13
  ProtocolUtils,
16
14
  IPerformanceClient,
17
15
  PerformanceEvents,
18
16
  invokeAsync,
17
+ invoke,
19
18
  } from "@azure/msal-common";
20
19
  import { StandardInteractionClient } from "./StandardInteractionClient";
21
20
  import { AuthorizationUrlRequest } from "../request/AuthorizationUrlRequest";
@@ -38,6 +37,7 @@ import { NativeInteractionClient } from "./NativeInteractionClient";
38
37
  import { AuthenticationResult } from "../response/AuthenticationResult";
39
38
  import { InteractionHandler } from "../interaction_handler/InteractionHandler";
40
39
  import * as BrowserUtils from "../utils/BrowserUtils";
40
+ import * as ResponseHandler from "../response/ResponseHandler";
41
41
 
42
42
  export class SilentIframeClient extends StandardInteractionClient {
43
43
  protected apiId: ApiId;
@@ -231,8 +231,9 @@ export class SilentIframeClient extends StandardInteractionClient {
231
231
  correlationId,
232
232
  this.config.system.navigateFrameWait
233
233
  );
234
+ const responseType = this.config.auth.OIDCOptions.serverResponseType;
234
235
  // Monitor the window for the hash. Return the string value and close the popup when the hash is received. Default timeout is 60 seconds.
235
- const hash = await invokeAsync(
236
+ const responseString = await invokeAsync(
236
237
  monitorIframeForHash,
237
238
  PerformanceEvents.SilentHandlerMonitorIframeForHash,
238
239
  this.logger,
@@ -244,26 +245,16 @@ export class SilentIframeClient extends StandardInteractionClient {
244
245
  this.config.system.pollIntervalMilliseconds,
245
246
  this.performanceClient,
246
247
  this.logger,
247
- correlationId
248
+ correlationId,
249
+ responseType
248
250
  );
249
- if (!hash) {
250
- // No hash is present
251
- this.logger.error(
252
- "The request has returned to the redirectUri but a hash is not present in the iframe. It's likely that the hash has been removed or the page has been redirected by code running on the redirectUri page."
253
- );
254
- throw createBrowserAuthError(BrowserAuthErrorCodes.hashEmptyError);
255
- } else if (!UrlString.hashContainsKnownProperties(hash)) {
256
- this.logger.error(
257
- "A hash is present in the iframe but it does not contain known properties. It's likely that the hash has been replaced by code running on the redirectUri page."
258
- );
259
- this.logger.errorPii(`The hash detected in the iframe is: ${hash}`);
260
- throw createBrowserAuthError(
261
- BrowserAuthErrorCodes.hashDoesNotContainKnownProperties
262
- );
263
- }
264
- // Deserialize hash fragment response parameters.
265
- const serverParams: ServerAuthorizationCodeResponse =
266
- UrlString.getDeserializedHash(hash);
251
+ const serverParams = invoke(
252
+ ResponseHandler.deserializeResponse,
253
+ PerformanceEvents.DeserializeResponse,
254
+ this.logger,
255
+ this.performanceClient,
256
+ this.correlationId
257
+ )(responseString, responseType, this.logger);
267
258
 
268
259
  if (serverParams.accountId) {
269
260
  this.logger.verbose(
@@ -309,13 +300,11 @@ export class SilentIframeClient extends StandardInteractionClient {
309
300
 
310
301
  // Handle response from hash string
311
302
  return invokeAsync(
312
- interactionHandler.handleCodeResponseFromHash.bind(
313
- interactionHandler
314
- ),
315
- PerformanceEvents.HandleCodeResponseFromHash,
303
+ interactionHandler.handleCodeResponse.bind(interactionHandler),
304
+ PerformanceEvents.HandleCodeResponse,
316
305
  this.logger,
317
306
  this.performanceClient,
318
307
  correlationId
319
- )(hash, silentRequest);
308
+ )(serverParams, silentRequest);
320
309
  }
321
310
  }
@@ -12,7 +12,6 @@ import {
12
12
  AuthorityOptions,
13
13
  Authority,
14
14
  AuthorityFactory,
15
- ServerAuthorizationCodeResponse,
16
15
  UrlString,
17
16
  CommonEndSessionRequest,
18
17
  ProtocolUtils,
@@ -28,14 +27,7 @@ import { BaseInteractionClient } from "./BaseInteractionClient";
28
27
  import { AuthorizationUrlRequest } from "../request/AuthorizationUrlRequest";
29
28
  import { BrowserConstants, InteractionType } from "../utils/BrowserConstants";
30
29
  import { version } from "../packageMetadata";
31
- import {
32
- createBrowserAuthError,
33
- BrowserAuthErrorCodes,
34
- } from "../error/BrowserAuthError";
35
- import {
36
- BrowserProtocolUtils,
37
- BrowserStateObject,
38
- } from "../utils/BrowserProtocolUtils";
30
+ import { BrowserStateObject } from "../utils/BrowserProtocolUtils";
39
31
  import { EndSessionRequest } from "../request/EndSessionRequest";
40
32
  import * as BrowserUtils from "../utils/BrowserUtils";
41
33
  import { RedirectRequest } from "../request/RedirectRequest";
@@ -57,7 +49,7 @@ export abstract class StandardInteractionClient extends BaseInteractionClient {
57
49
  ): Promise<CommonAuthorizationCodeRequest> {
58
50
  this.performanceClient.addQueueMeasurement(
59
51
  PerformanceEvents.StandardInteractionClientInitializeAuthorizationCodeRequest,
60
- request.correlationId
52
+ this.correlationId
61
53
  );
62
54
  const generatedPkceParams = await invokeAsync(
63
55
  generatePkceCodes,
@@ -294,44 +286,6 @@ export abstract class StandardInteractionClient extends BaseInteractionClient {
294
286
  };
295
287
  }
296
288
 
297
- /**
298
- * @param hash
299
- * @param interactionType
300
- */
301
- protected validateAndExtractStateFromHash(
302
- serverParams: ServerAuthorizationCodeResponse,
303
- interactionType: InteractionType,
304
- requestCorrelationId?: string
305
- ): string {
306
- this.logger.verbose(
307
- "validateAndExtractStateFromHash called",
308
- requestCorrelationId
309
- );
310
- if (!serverParams.state) {
311
- throw createBrowserAuthError(BrowserAuthErrorCodes.noStateInHash);
312
- }
313
-
314
- const platformStateObj =
315
- BrowserProtocolUtils.extractBrowserRequestState(
316
- this.browserCrypto,
317
- serverParams.state
318
- );
319
- if (!platformStateObj) {
320
- throw createBrowserAuthError(
321
- BrowserAuthErrorCodes.unableToParseState
322
- );
323
- }
324
-
325
- if (platformStateObj.interactionType !== interactionType) {
326
- throw createBrowserAuthError(
327
- BrowserAuthErrorCodes.stateInteractionTypeMismatch
328
- );
329
- }
330
-
331
- this.logger.verbose("Returning state from hash", requestCorrelationId);
332
- return serverParams.state;
333
- }
334
-
335
289
  /**
336
290
  * Used to get a discovered version of the default authority.
337
291
  * @param requestAuthority
@@ -14,6 +14,7 @@ import {
14
14
  PerformanceEvents,
15
15
  invokeAsync,
16
16
  CcsCredentialType,
17
+ ServerAuthorizationCodeResponse,
17
18
  } from "@azure/msal-common";
18
19
 
19
20
  import { BrowserCacheManager } from "../cache/BrowserCacheManager";
@@ -52,23 +53,19 @@ export class InteractionHandler {
52
53
  * Function to handle response parameters from hash.
53
54
  * @param locationHash
54
55
  */
55
- async handleCodeResponseFromHash(
56
- locationHash: string,
56
+ async handleCodeResponse(
57
+ response: ServerAuthorizationCodeResponse,
57
58
  request: AuthorizationUrlRequest
58
59
  ): Promise<AuthenticationResult> {
59
60
  this.performanceClient.addQueueMeasurement(
60
- PerformanceEvents.HandleCodeResponseFromHash,
61
+ PerformanceEvents.HandleCodeResponse,
61
62
  request.correlationId
62
63
  );
63
- // Check that location hash isn't empty.
64
- if (!locationHash) {
65
- throw createBrowserAuthError(BrowserAuthErrorCodes.hashEmptyError);
66
- }
67
64
 
68
65
  let authCodeResponse;
69
66
  try {
70
67
  authCodeResponse = this.authModule.handleFragmentResponse(
71
- locationHash,
68
+ response,
72
69
  request.state
73
70
  );
74
71
  } catch (e) {
@@ -14,6 +14,7 @@ import {
14
14
  CcsCredential,
15
15
  invokeAsync,
16
16
  PerformanceEvents,
17
+ ServerAuthorizationCodeResponse,
17
18
  } from "@azure/msal-common";
18
19
  import {
19
20
  createBrowserAuthError,
@@ -141,17 +142,12 @@ export class RedirectHandler {
141
142
  * Handle authorization code response in the window.
142
143
  * @param hash
143
144
  */
144
- async handleCodeResponseFromHash(
145
- locationHash: string,
145
+ async handleCodeResponse(
146
+ response: ServerAuthorizationCodeResponse,
146
147
  state: string
147
148
  ): Promise<AuthenticationResult> {
148
149
  this.logger.verbose("RedirectHandler.handleCodeResponse called");
149
150
 
150
- // Check that location hash isn't empty.
151
- if (!locationHash) {
152
- throw createBrowserAuthError(BrowserAuthErrorCodes.hashEmptyError);
153
- }
154
-
155
151
  // Interaction is completed - remove interaction status.
156
152
  this.browserStorage.setInteractionInProgress(false);
157
153
 
@@ -168,7 +164,7 @@ export class RedirectHandler {
168
164
  let authCodeResponse;
169
165
  try {
170
166
  authCodeResponse = this.authModule.handleFragmentResponse(
171
- locationHash,
167
+ response,
172
168
  requestState
173
169
  );
174
170
  } catch (e) {
@@ -9,6 +9,7 @@ import {
9
9
  PerformanceEvents,
10
10
  invokeAsync,
11
11
  invoke,
12
+ ServerResponseType,
12
13
  } from "@azure/msal-common";
13
14
  import {
14
15
  createBrowserAuthError,
@@ -67,7 +68,8 @@ export async function monitorIframeForHash(
67
68
  pollIntervalMilliseconds: number,
68
69
  performanceClient: IPerformanceClient,
69
70
  logger: Logger,
70
- correlationId: string
71
+ correlationId: string,
72
+ responseType: ServerResponseType
71
73
  ): Promise<string> {
72
74
  performanceClient.addQueueMeasurement(
73
75
  PerformanceEvents.SilentHandlerMonitorIframeForHash,
@@ -110,12 +112,17 @@ export async function monitorIframeForHash(
110
112
  return;
111
113
  }
112
114
 
113
- const contentHash = contentWindow
114
- ? contentWindow.location.hash
115
- : "";
115
+ let responseString = "";
116
+ if (contentWindow) {
117
+ if (responseType === ServerResponseType.QUERY) {
118
+ responseString = contentWindow.location.search;
119
+ } else {
120
+ responseString = contentWindow.location.hash;
121
+ }
122
+ }
116
123
  window.clearTimeout(timeoutId);
117
124
  window.clearInterval(intervalId);
118
- resolve(contentHash);
125
+ resolve(responseString);
119
126
  }, pollIntervalMilliseconds);
120
127
  }).finally(() => {
121
128
  invoke(
@@ -1,3 +1,3 @@
1
1
  /* eslint-disable header/header */
2
2
  export const name = "@azure/msal-browser";
3
- export const version = "3.4.0";
3
+ export const version = "3.5.0";
@@ -0,0 +1,73 @@
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ import {
7
+ ICrypto,
8
+ Logger,
9
+ ServerAuthorizationCodeResponse,
10
+ UrlUtils,
11
+ } from "@azure/msal-common";
12
+ import {
13
+ BrowserAuthErrorCodes,
14
+ createBrowserAuthError,
15
+ } from "../error/BrowserAuthError";
16
+ import { extractBrowserRequestState } from "../utils/BrowserProtocolUtils";
17
+ import { InteractionType } from "../utils/BrowserConstants";
18
+
19
+ export function deserializeResponse(
20
+ responseString: string,
21
+ responseLocation: string,
22
+ logger: Logger
23
+ ): ServerAuthorizationCodeResponse {
24
+ // Deserialize hash fragment response parameters.
25
+ const serverParams = UrlUtils.getDeserializedResponse(responseString);
26
+ if (!serverParams) {
27
+ if (!UrlUtils.stripLeadingHashOrQuery(responseString)) {
28
+ // Hash or Query string is empty
29
+ logger.error(
30
+ `The request has returned to the redirectUri but a ${responseLocation} is not present. It's likely that the ${responseLocation} has been removed or the page has been redirected by code running on the redirectUri page.`
31
+ );
32
+ throw createBrowserAuthError(BrowserAuthErrorCodes.hashEmptyError);
33
+ } else {
34
+ logger.error(
35
+ `A ${responseLocation} is present in the iframe but it does not contain known properties. It's likely that the ${responseLocation} has been replaced by code running on the redirectUri page.`
36
+ );
37
+ logger.errorPii(
38
+ `The ${responseLocation} detected is: ${responseString}`
39
+ );
40
+ throw createBrowserAuthError(
41
+ BrowserAuthErrorCodes.hashDoesNotContainKnownProperties
42
+ );
43
+ }
44
+ }
45
+ return serverParams;
46
+ }
47
+
48
+ /**
49
+ * Returns the interaction type that the response object belongs to
50
+ */
51
+ export function validateInteractionType(
52
+ response: ServerAuthorizationCodeResponse,
53
+ browserCrypto: ICrypto,
54
+ interactionType: InteractionType
55
+ ): void {
56
+ if (!response.state) {
57
+ throw createBrowserAuthError(BrowserAuthErrorCodes.noStateInHash);
58
+ }
59
+
60
+ const platformStateObj = extractBrowserRequestState(
61
+ browserCrypto,
62
+ response.state
63
+ );
64
+ if (!platformStateObj) {
65
+ throw createBrowserAuthError(BrowserAuthErrorCodes.unableToParseState);
66
+ }
67
+
68
+ if (platformStateObj.interactionType !== interactionType) {
69
+ throw createBrowserAuthError(
70
+ BrowserAuthErrorCodes.stateInteractionTypeMismatch
71
+ );
72
+ }
73
+ }
@@ -8,8 +8,6 @@ import {
8
8
  ICrypto,
9
9
  RequestStateObject,
10
10
  ProtocolUtils,
11
- ServerAuthorizationCodeResponse,
12
- UrlString,
13
11
  createClientAuthError,
14
12
  ClientAuthErrorCodes,
15
13
  } from "@azure/msal-common";
@@ -18,41 +16,24 @@ export type BrowserStateObject = {
18
16
  interactionType: InteractionType;
19
17
  };
20
18
 
21
- export class BrowserProtocolUtils {
22
- /**
23
- * Extracts the BrowserStateObject from the state string.
24
- * @param browserCrypto
25
- * @param state
26
- */
27
- static extractBrowserRequestState(
28
- browserCrypto: ICrypto,
29
- state: string
30
- ): BrowserStateObject | null {
31
- if (!state) {
32
- return null;
33
- }
34
-
35
- try {
36
- const requestStateObj: RequestStateObject =
37
- ProtocolUtils.parseRequestState(browserCrypto, state);
38
- return requestStateObj.libraryState.meta as BrowserStateObject;
39
- } catch (e) {
40
- throw createClientAuthError(ClientAuthErrorCodes.invalidState);
41
- }
19
+ /**
20
+ * Extracts the BrowserStateObject from the state string.
21
+ * @param browserCrypto
22
+ * @param state
23
+ */
24
+ export function extractBrowserRequestState(
25
+ browserCrypto: ICrypto,
26
+ state: string
27
+ ): BrowserStateObject | null {
28
+ if (!state) {
29
+ return null;
42
30
  }
43
31
 
44
- /**
45
- * Parses properties of server response from url hash
46
- * @param locationHash Hash from url
47
- */
48
- static parseServerResponseFromHash(
49
- locationHash: string
50
- ): ServerAuthorizationCodeResponse {
51
- if (!locationHash) {
52
- return {};
53
- }
54
-
55
- const hashUrlString = new UrlString(locationHash);
56
- return UrlString.getDeserializedHash(hashUrlString.getHash());
32
+ try {
33
+ const requestStateObj: RequestStateObject =
34
+ ProtocolUtils.parseRequestState(browserCrypto, state);
35
+ return requestStateObj.libraryState.meta as BrowserStateObject;
36
+ } catch (e) {
37
+ throw createClientAuthError(ClientAuthErrorCodes.invalidState);
57
38
  }
58
39
  }