@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.
- package/dist/app/IPublicClientApplication.mjs +1 -1
- package/dist/app/PublicClientApplication.mjs +1 -1
- package/dist/app/PublicClientNext.mjs +1 -1
- package/dist/broker/nativeBroker/NativeMessageHandler.mjs +1 -1
- package/dist/broker/nativeBroker/NativeStatusCodes.mjs +1 -1
- package/dist/cache/AsyncMemoryStorage.mjs +1 -1
- package/dist/cache/BrowserCacheManager.d.ts.map +1 -1
- package/dist/cache/BrowserCacheManager.mjs +8 -8
- package/dist/cache/BrowserCacheManager.mjs.map +1 -1
- package/dist/cache/BrowserStorage.mjs +1 -1
- package/dist/cache/CryptoKeyStore.mjs +1 -1
- package/dist/cache/DatabaseStorage.mjs +1 -1
- package/dist/cache/MemoryStorage.mjs +1 -1
- package/dist/cache/TokenCache.mjs +1 -1
- package/dist/config/Configuration.mjs +1 -1
- package/dist/controllers/ControllerFactory.mjs +1 -1
- package/dist/controllers/NestedAppAuthController.mjs +1 -1
- package/dist/controllers/StandardController.d.ts.map +1 -1
- package/dist/controllers/StandardController.mjs +23 -22
- package/dist/controllers/StandardController.mjs.map +1 -1
- package/dist/controllers/UnknownOperatingContextController.mjs +1 -1
- package/dist/crypto/BrowserCrypto.mjs +1 -1
- package/dist/crypto/CryptoOps.d.ts +2 -2
- package/dist/crypto/CryptoOps.d.ts.map +1 -1
- package/dist/crypto/CryptoOps.mjs +4 -3
- package/dist/crypto/CryptoOps.mjs.map +1 -1
- package/dist/crypto/PkceGenerator.mjs +1 -1
- package/dist/crypto/SignedHttpRequest.mjs +1 -1
- package/dist/encode/Base64Decode.mjs +1 -1
- package/dist/encode/Base64Encode.mjs +1 -1
- package/dist/error/BrowserAuthError.mjs +1 -1
- package/dist/error/BrowserAuthErrorCodes.mjs +1 -1
- package/dist/error/BrowserConfigurationAuthError.mjs +1 -1
- package/dist/error/BrowserConfigurationAuthErrorCodes.mjs +1 -1
- package/dist/error/NativeAuthError.mjs +1 -1
- package/dist/error/NativeAuthErrorCodes.mjs +1 -1
- package/dist/error/NestedAppAuthError.mjs +1 -1
- package/dist/event/EventHandler.mjs +1 -1
- package/dist/event/EventMessage.mjs +1 -1
- package/dist/event/EventType.mjs +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/interaction_client/BaseInteractionClient.d.ts +0 -1
- package/dist/interaction_client/BaseInteractionClient.d.ts.map +1 -1
- package/dist/interaction_client/BaseInteractionClient.mjs +2 -3
- package/dist/interaction_client/BaseInteractionClient.mjs.map +1 -1
- package/dist/interaction_client/HybridSpaAuthorizationCodeClient.mjs +1 -1
- package/dist/interaction_client/NativeInteractionClient.mjs +1 -1
- package/dist/interaction_client/PopupClient.d.ts +0 -10
- package/dist/interaction_client/PopupClient.d.ts.map +1 -1
- package/dist/interaction_client/PopupClient.mjs +22 -92
- package/dist/interaction_client/PopupClient.mjs.map +1 -1
- package/dist/interaction_client/RedirectClient.d.ts +3 -3
- package/dist/interaction_client/RedirectClient.d.ts.map +1 -1
- package/dist/interaction_client/RedirectClient.mjs +51 -34
- package/dist/interaction_client/RedirectClient.mjs.map +1 -1
- package/dist/interaction_client/SilentAuthCodeClient.mjs +1 -1
- package/dist/interaction_client/SilentCacheClient.mjs +1 -1
- package/dist/interaction_client/SilentIframeClient.d.ts.map +1 -1
- package/dist/interaction_client/SilentIframeClient.mjs +8 -17
- package/dist/interaction_client/SilentIframeClient.mjs.map +1 -1
- package/dist/interaction_client/SilentRefreshClient.mjs +1 -1
- package/dist/interaction_client/StandardInteractionClient.d.ts +1 -6
- package/dist/interaction_client/StandardInteractionClient.d.ts.map +1 -1
- package/dist/interaction_client/StandardInteractionClient.mjs +2 -24
- package/dist/interaction_client/StandardInteractionClient.mjs.map +1 -1
- package/dist/interaction_handler/InteractionHandler.d.ts +2 -2
- package/dist/interaction_handler/InteractionHandler.d.ts.map +1 -1
- package/dist/interaction_handler/InteractionHandler.mjs +5 -9
- package/dist/interaction_handler/InteractionHandler.mjs.map +1 -1
- package/dist/interaction_handler/RedirectHandler.d.ts +2 -2
- package/dist/interaction_handler/RedirectHandler.d.ts.map +1 -1
- package/dist/interaction_handler/RedirectHandler.mjs +4 -8
- package/dist/interaction_handler/RedirectHandler.mjs.map +1 -1
- package/dist/interaction_handler/SilentHandler.d.ts +2 -2
- package/dist/interaction_handler/SilentHandler.d.ts.map +1 -1
- package/dist/interaction_handler/SilentHandler.mjs +13 -7
- package/dist/interaction_handler/SilentHandler.mjs.map +1 -1
- package/dist/naa/BridgeError.mjs +1 -1
- package/dist/naa/BridgeProxy.mjs +1 -1
- package/dist/naa/BridgeStatusCode.mjs +1 -1
- package/dist/naa/mapping/NestedAppAuthAdapter.mjs +1 -1
- package/dist/navigation/NavigationClient.mjs +1 -1
- package/dist/network/FetchClient.mjs +1 -1
- package/dist/operatingcontext/BaseOperatingContext.mjs +1 -1
- package/dist/operatingcontext/StandardOperatingContext.mjs +1 -1
- package/dist/operatingcontext/TeamsAppOperatingContext.mjs +1 -1
- package/dist/operatingcontext/UnknownOperatingContext.mjs +1 -1
- package/dist/packageMetadata.d.ts +1 -1
- package/dist/packageMetadata.mjs +2 -2
- package/dist/response/ResponseHandler.d.ts +8 -0
- package/dist/response/ResponseHandler.d.ts.map +1 -0
- package/dist/response/ResponseHandler.mjs +46 -0
- package/dist/response/ResponseHandler.mjs.map +1 -0
- package/dist/telemetry/BrowserPerformanceClient.mjs +1 -1
- package/dist/telemetry/BrowserPerformanceMeasurement.mjs +1 -1
- package/dist/utils/BrowserConstants.mjs +1 -1
- package/dist/utils/BrowserProtocolUtils.d.ts +7 -14
- package/dist/utils/BrowserProtocolUtils.d.ts.map +1 -1
- package/dist/utils/BrowserProtocolUtils.mjs +17 -30
- package/dist/utils/BrowserProtocolUtils.mjs.map +1 -1
- package/dist/utils/BrowserUtils.mjs +1 -1
- package/lib/msal-browser.cjs +360 -490
- package/lib/msal-browser.cjs.map +1 -1
- package/lib/msal-browser.js +360 -490
- package/lib/msal-browser.js.map +1 -1
- package/lib/msal-browser.min.js +66 -65
- package/package.json +2 -2
- package/src/cache/BrowserCacheManager.ts +7 -10
- package/src/controllers/StandardController.ts +28 -39
- package/src/crypto/CryptoOps.ts +5 -3
- package/src/index.ts +1 -0
- package/src/interaction_client/BaseInteractionClient.ts +1 -2
- package/src/interaction_client/PopupClient.ts +34 -137
- package/src/interaction_client/RedirectClient.ts +71 -55
- package/src/interaction_client/SilentIframeClient.ts +16 -27
- package/src/interaction_client/StandardInteractionClient.ts +2 -48
- package/src/interaction_handler/InteractionHandler.ts +5 -8
- package/src/interaction_handler/RedirectHandler.ts +4 -8
- package/src/interaction_handler/SilentHandler.ts +12 -5
- package/src/packageMetadata.ts +1 -1
- package/src/response/ResponseHandler.ts +73 -0
- 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
|
|
205
|
-
hash ||
|
|
207
|
+
const [serverParams, responseString] = this.getRedirectResponse(
|
|
208
|
+
hash || ""
|
|
206
209
|
);
|
|
207
|
-
if (!
|
|
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
|
|
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
|
|
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
|
|
255
|
+
"NavigateToLoginRequestUrl set to false, handling response"
|
|
273
256
|
);
|
|
274
|
-
return this.
|
|
275
|
-
|
|
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
|
-
|
|
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.
|
|
335
|
-
|
|
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
|
|
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
|
-
|
|
364
|
-
|
|
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
|
|
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
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
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
|
|
394
|
-
|
|
395
|
-
state: string,
|
|
408
|
+
protected async handleResponse(
|
|
409
|
+
serverParams: ServerAuthorizationCodeResponse,
|
|
396
410
|
serverTelemetryManager: ServerTelemetryManager
|
|
397
411
|
): Promise<AuthenticationResult> {
|
|
398
|
-
const
|
|
399
|
-
|
|
412
|
+
const state = serverParams.state;
|
|
413
|
+
if (!state) {
|
|
414
|
+
throw createBrowserAuthError(BrowserAuthErrorCodes.noStateInHash);
|
|
415
|
+
}
|
|
400
416
|
|
|
401
|
-
const
|
|
402
|
-
|
|
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.
|
|
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
|
|
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
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
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.
|
|
313
|
-
|
|
314
|
-
),
|
|
315
|
-
PerformanceEvents.HandleCodeResponseFromHash,
|
|
303
|
+
interactionHandler.handleCodeResponse.bind(interactionHandler),
|
|
304
|
+
PerformanceEvents.HandleCodeResponse,
|
|
316
305
|
this.logger,
|
|
317
306
|
this.performanceClient,
|
|
318
307
|
correlationId
|
|
319
|
-
)(
|
|
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
|
-
|
|
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
|
|
56
|
-
|
|
56
|
+
async handleCodeResponse(
|
|
57
|
+
response: ServerAuthorizationCodeResponse,
|
|
57
58
|
request: AuthorizationUrlRequest
|
|
58
59
|
): Promise<AuthenticationResult> {
|
|
59
60
|
this.performanceClient.addQueueMeasurement(
|
|
60
|
-
PerformanceEvents.
|
|
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
|
-
|
|
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
|
|
145
|
-
|
|
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
|
-
|
|
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
|
-
|
|
114
|
-
|
|
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(
|
|
125
|
+
resolve(responseString);
|
|
119
126
|
}, pollIntervalMilliseconds);
|
|
120
127
|
}).finally(() => {
|
|
121
128
|
invoke(
|
package/src/packageMetadata.ts
CHANGED
|
@@ -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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
)
|
|
31
|
-
|
|
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
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
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
|
}
|