@azure/msal-common 14.0.2 → 14.0.3
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/account/AuthToken.d.ts +14 -17
- package/dist/account/AuthToken.d.ts.map +1 -1
- package/dist/account/AuthToken.mjs +48 -39
- package/dist/account/AuthToken.mjs.map +1 -1
- package/dist/account/CcsCredential.mjs +1 -1
- package/dist/account/CcsCredential.mjs.map +1 -1
- package/dist/account/ClientInfo.d.ts.map +1 -1
- package/dist/account/ClientInfo.mjs +3 -4
- package/dist/account/ClientInfo.mjs.map +1 -1
- package/dist/authority/Authority.mjs +1 -1
- package/dist/authority/Authority.mjs.map +1 -1
- package/dist/authority/AuthorityFactory.d.ts.map +1 -1
- package/dist/authority/AuthorityFactory.mjs +2 -3
- package/dist/authority/AuthorityFactory.mjs.map +1 -1
- package/dist/authority/AuthorityMetadata.mjs +1 -1
- package/dist/authority/AuthorityMetadata.mjs.map +1 -1
- package/dist/authority/AuthorityOptions.mjs +1 -1
- package/dist/authority/AuthorityOptions.mjs.map +1 -1
- package/dist/authority/AuthorityType.mjs +1 -1
- package/dist/authority/AuthorityType.mjs.map +1 -1
- package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs +1 -1
- package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs.map +1 -1
- package/dist/authority/CloudInstanceDiscoveryResponse.mjs +1 -1
- package/dist/authority/CloudInstanceDiscoveryResponse.mjs.map +1 -1
- package/dist/authority/OpenIdConfigResponse.mjs +1 -1
- package/dist/authority/OpenIdConfigResponse.mjs.map +1 -1
- package/dist/authority/ProtocolMode.mjs +1 -1
- package/dist/authority/ProtocolMode.mjs.map +1 -1
- package/dist/authority/RegionDiscovery.mjs +1 -1
- package/dist/authority/RegionDiscovery.mjs.map +1 -1
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.mjs +5 -5
- package/dist/cache/CacheManager.mjs.map +1 -1
- package/dist/cache/entities/AccessTokenEntity.d.ts.map +1 -1
- package/dist/cache/entities/AccessTokenEntity.mjs +4 -7
- package/dist/cache/entities/AccessTokenEntity.mjs.map +1 -1
- package/dist/cache/entities/AccountEntity.d.ts.map +1 -1
- package/dist/cache/entities/AccountEntity.mjs +2 -4
- package/dist/cache/entities/AccountEntity.mjs.map +1 -1
- package/dist/cache/entities/AppMetadataEntity.mjs +1 -1
- package/dist/cache/entities/AppMetadataEntity.mjs.map +1 -1
- package/dist/cache/entities/AuthorityMetadataEntity.mjs +1 -1
- package/dist/cache/entities/AuthorityMetadataEntity.mjs.map +1 -1
- package/dist/cache/entities/CacheRecord.mjs +1 -1
- package/dist/cache/entities/CacheRecord.mjs.map +1 -1
- package/dist/cache/entities/CredentialEntity.mjs +1 -1
- package/dist/cache/entities/CredentialEntity.mjs.map +1 -1
- package/dist/cache/entities/IdTokenEntity.mjs +1 -1
- package/dist/cache/entities/IdTokenEntity.mjs.map +1 -1
- package/dist/cache/entities/RefreshTokenEntity.mjs +1 -1
- package/dist/cache/entities/RefreshTokenEntity.mjs.map +1 -1
- package/dist/cache/entities/ServerTelemetryEntity.mjs +1 -1
- package/dist/cache/entities/ServerTelemetryEntity.mjs.map +1 -1
- package/dist/cache/entities/ThrottlingEntity.mjs +1 -1
- package/dist/cache/entities/ThrottlingEntity.mjs.map +1 -1
- package/dist/cache/persistence/TokenCacheContext.mjs +1 -1
- package/dist/cache/persistence/TokenCacheContext.mjs.map +1 -1
- package/dist/client/AuthorizationCodeClient.d.ts.map +1 -1
- package/dist/client/AuthorizationCodeClient.mjs +10 -39
- package/dist/client/AuthorizationCodeClient.mjs.map +1 -1
- package/dist/client/BaseClient.d.ts +1 -1
- package/dist/client/BaseClient.d.ts.map +1 -1
- package/dist/client/BaseClient.mjs +8 -2
- package/dist/client/BaseClient.mjs.map +1 -1
- package/dist/client/RefreshTokenClient.d.ts.map +1 -1
- package/dist/client/RefreshTokenClient.mjs +2 -11
- package/dist/client/RefreshTokenClient.mjs.map +1 -1
- package/dist/client/SilentFlowClient.d.ts.map +1 -1
- package/dist/client/SilentFlowClient.mjs +7 -7
- package/dist/client/SilentFlowClient.mjs.map +1 -1
- package/dist/config/ClientConfiguration.mjs +1 -1
- package/dist/config/ClientConfiguration.mjs.map +1 -1
- package/dist/crypto/ICrypto.mjs +1 -1
- package/dist/crypto/ICrypto.mjs.map +1 -1
- package/dist/crypto/JoseHeader.mjs +1 -1
- package/dist/crypto/JoseHeader.mjs.map +1 -1
- package/dist/crypto/PopTokenGenerator.mjs +1 -1
- package/dist/crypto/PopTokenGenerator.mjs.map +1 -1
- package/dist/error/AuthError.mjs +1 -1
- package/dist/error/AuthError.mjs.map +1 -1
- package/dist/error/ClientAuthError.mjs +1 -1
- package/dist/error/ClientAuthError.mjs.map +1 -1
- package/dist/error/ClientConfigurationError.mjs +1 -1
- package/dist/error/ClientConfigurationError.mjs.map +1 -1
- package/dist/error/InteractionRequiredAuthError.mjs +1 -1
- package/dist/error/InteractionRequiredAuthError.mjs.map +1 -1
- package/dist/error/JoseHeaderError.mjs +1 -1
- package/dist/error/JoseHeaderError.mjs.map +1 -1
- package/dist/error/ServerError.mjs +1 -1
- package/dist/error/ServerError.mjs.map +1 -1
- package/dist/index.cjs +1641 -1560
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.mjs +5 -3
- package/dist/index.mjs.map +1 -1
- package/dist/logger/Logger.d.ts.map +1 -1
- package/dist/logger/Logger.mjs +2 -12
- package/dist/logger/Logger.mjs.map +1 -1
- package/dist/network/INetworkModule.mjs +1 -1
- package/dist/network/INetworkModule.mjs.map +1 -1
- package/dist/network/NetworkManager.mjs +1 -1
- package/dist/network/NetworkManager.mjs.map +1 -1
- package/dist/network/ThrottlingUtils.mjs +1 -1
- package/dist/network/ThrottlingUtils.mjs.map +1 -1
- package/dist/packageMetadata.d.ts +1 -1
- package/dist/packageMetadata.mjs +2 -2
- package/dist/packageMetadata.mjs.map +1 -1
- package/dist/request/AuthenticationHeaderParser.mjs +1 -1
- package/dist/request/AuthenticationHeaderParser.mjs.map +1 -1
- package/dist/request/RequestParameterBuilder.d.ts.map +1 -1
- package/dist/request/RequestParameterBuilder.mjs +6 -7
- package/dist/request/RequestParameterBuilder.mjs.map +1 -1
- package/dist/request/RequestValidator.d.ts.map +1 -1
- package/dist/request/RequestValidator.mjs +4 -6
- package/dist/request/RequestValidator.mjs.map +1 -1
- package/dist/request/ScopeSet.mjs +4 -4
- package/dist/request/ScopeSet.mjs.map +1 -1
- package/dist/response/AuthenticationResult.d.ts +3 -1
- package/dist/response/AuthenticationResult.d.ts.map +1 -1
- package/dist/response/ResponseHandler.d.ts +4 -3
- package/dist/response/ResponseHandler.d.ts.map +1 -1
- package/dist/response/ResponseHandler.mjs +57 -39
- package/dist/response/ResponseHandler.mjs.map +1 -1
- package/dist/response/ServerAuthorizationTokenResponse.d.ts +2 -0
- package/dist/response/ServerAuthorizationTokenResponse.d.ts.map +1 -1
- package/dist/telemetry/performance/IPerformanceClient.d.ts +4 -4
- package/dist/telemetry/performance/IPerformanceClient.d.ts.map +1 -1
- package/dist/telemetry/performance/PerformanceClient.d.ts +2 -2
- package/dist/telemetry/performance/PerformanceClient.d.ts.map +1 -1
- package/dist/telemetry/performance/PerformanceClient.mjs +1 -1
- package/dist/telemetry/performance/PerformanceClient.mjs.map +1 -1
- package/dist/telemetry/performance/PerformanceEvent.d.ts +8 -1
- package/dist/telemetry/performance/PerformanceEvent.d.ts.map +1 -1
- package/dist/telemetry/performance/PerformanceEvent.mjs +9 -1
- package/dist/telemetry/performance/PerformanceEvent.mjs.map +1 -1
- package/dist/telemetry/performance/StubPerformanceClient.d.ts +3 -3
- package/dist/telemetry/performance/StubPerformanceClient.d.ts.map +1 -1
- package/dist/telemetry/performance/StubPerformanceClient.mjs +23 -3
- package/dist/telemetry/performance/StubPerformanceClient.mjs.map +1 -1
- package/dist/telemetry/server/ServerTelemetryManager.d.ts.map +1 -1
- package/dist/telemetry/server/ServerTelemetryManager.mjs +3 -4
- package/dist/telemetry/server/ServerTelemetryManager.mjs.map +1 -1
- package/dist/url/UrlString.d.ts.map +1 -1
- package/dist/url/UrlString.mjs +10 -12
- package/dist/url/UrlString.mjs.map +1 -1
- package/dist/utils/Constants.d.ts +10 -0
- package/dist/utils/Constants.d.ts.map +1 -1
- package/dist/utils/Constants.mjs +11 -2
- package/dist/utils/Constants.mjs.map +1 -1
- package/dist/utils/FunctionWrappers.d.ts +28 -0
- package/dist/utils/FunctionWrappers.d.ts.map +1 -0
- package/dist/utils/FunctionWrappers.mjs +90 -0
- package/dist/utils/FunctionWrappers.mjs.map +1 -0
- package/dist/utils/ProtocolUtils.d.ts.map +1 -1
- package/dist/utils/ProtocolUtils.mjs +4 -7
- package/dist/utils/ProtocolUtils.mjs.map +1 -1
- package/dist/utils/StringUtils.d.ts +0 -13
- package/dist/utils/StringUtils.d.ts.map +1 -1
- package/dist/utils/StringUtils.mjs +3 -34
- package/dist/utils/StringUtils.mjs.map +1 -1
- package/dist/utils/TimeUtils.mjs +1 -1
- package/dist/utils/TimeUtils.mjs.map +1 -1
- package/package.json +6 -4
- package/src/account/AccountInfo.ts +44 -0
- package/src/account/AuthToken.ts +70 -0
- package/src/account/CcsCredential.ts +16 -0
- package/src/account/ClientCredentials.ts +20 -0
- package/src/account/ClientInfo.ts +64 -0
- package/src/account/TokenClaims.ts +70 -0
- package/src/authority/Authority.ts +1225 -0
- package/src/authority/AuthorityFactory.ts +106 -0
- package/src/authority/AuthorityMetadata.ts +953 -0
- package/src/authority/AuthorityOptions.ts +40 -0
- package/src/authority/AuthorityType.ts +15 -0
- package/src/authority/AzureRegion.ts +7 -0
- package/src/authority/AzureRegionConfiguration.ts +16 -0
- package/src/authority/CloudDiscoveryMetadata.ts +10 -0
- package/src/authority/CloudInstanceDiscoveryErrorResponse.ts +26 -0
- package/src/authority/CloudInstanceDiscoveryResponse.ts +21 -0
- package/src/authority/ImdsOptions.ts +10 -0
- package/src/authority/OIDCOptions.ts +14 -0
- package/src/authority/OpenIdConfigResponse.ts +24 -0
- package/src/authority/ProtocolMode.ts +13 -0
- package/src/authority/RegionDiscovery.ts +193 -0
- package/src/authority/RegionDiscoveryMetadata.ts +15 -0
- package/src/broker/nativeBroker/INativeBrokerPlugin.ts +29 -0
- package/src/cache/CacheManager.ts +1619 -0
- package/src/cache/entities/AccessTokenEntity.ts +162 -0
- package/src/cache/entities/AccountEntity.ts +309 -0
- package/src/cache/entities/AppMetadataEntity.ts +91 -0
- package/src/cache/entities/AuthorityMetadataEntity.ts +112 -0
- package/src/cache/entities/CacheRecord.ts +33 -0
- package/src/cache/entities/CredentialEntity.ts +215 -0
- package/src/cache/entities/IdTokenEntity.ts +74 -0
- package/src/cache/entities/RefreshTokenEntity.ts +78 -0
- package/src/cache/entities/ServerTelemetryEntity.ts +38 -0
- package/src/cache/entities/ThrottlingEntity.ts +36 -0
- package/src/cache/interface/ICacheManager.ts +218 -0
- package/src/cache/interface/ICachePlugin.ts +11 -0
- package/src/cache/interface/ISerializableTokenCache.ts +9 -0
- package/src/cache/persistence/TokenCacheContext.ts +39 -0
- package/src/cache/utils/CacheTypes.ts +93 -0
- package/src/client/AuthorizationCodeClient.ts +714 -0
- package/src/client/BaseClient.ts +205 -0
- package/src/client/RefreshTokenClient.ts +442 -0
- package/src/client/SilentFlowClient.ts +186 -0
- package/src/config/AppTokenProvider.ts +47 -0
- package/src/config/ClientConfiguration.ts +287 -0
- package/src/crypto/ICrypto.ts +127 -0
- package/src/crypto/IGuidGenerator.ts +9 -0
- package/src/crypto/JoseHeader.ts +55 -0
- package/src/crypto/PopTokenGenerator.ts +155 -0
- package/src/crypto/SignedHttpRequest.ts +16 -0
- package/src/error/AuthError.ts +85 -0
- package/src/error/ClientAuthError.ts +738 -0
- package/src/error/ClientConfigurationError.ts +396 -0
- package/src/error/InteractionRequiredAuthError.ts +134 -0
- package/src/error/JoseHeaderError.ts +52 -0
- package/src/error/ServerError.ts +18 -0
- package/src/index.ts +215 -0
- package/src/logger/Logger.ts +272 -0
- package/src/network/INetworkModule.ts +57 -0
- package/src/network/NetworkManager.ts +76 -0
- package/src/network/RequestThumbprint.ts +22 -0
- package/src/network/ThrottlingUtils.ts +156 -0
- package/src/packageMetadata.ts +3 -0
- package/src/request/AuthenticationHeaderParser.ts +89 -0
- package/src/request/BaseAuthRequest.ts +46 -0
- package/src/request/CommonAuthorizationCodeRequest.ts +33 -0
- package/src/request/CommonAuthorizationUrlRequest.ts +56 -0
- package/src/request/CommonClientCredentialRequest.ts +23 -0
- package/src/request/CommonDeviceCodeRequest.ts +31 -0
- package/src/request/CommonEndSessionRequest.ts +27 -0
- package/src/request/CommonOnBehalfOfRequest.ts +19 -0
- package/src/request/CommonRefreshTokenRequest.ts +25 -0
- package/src/request/CommonSilentFlowRequest.ts +24 -0
- package/src/request/CommonUsernamePasswordRequest.ts +23 -0
- package/src/request/NativeRequest.ts +25 -0
- package/src/request/NativeSignOutRequest.ts +10 -0
- package/src/request/RequestParameterBuilder.ts +606 -0
- package/src/request/RequestValidator.ts +103 -0
- package/src/request/ScopeSet.ts +230 -0
- package/src/request/StoreInCache.ts +16 -0
- package/src/response/AuthenticationResult.ts +47 -0
- package/src/response/AuthorizationCodePayload.ts +18 -0
- package/src/response/DeviceCodeResponse.ts +31 -0
- package/src/response/ExternalTokenResponse.ts +24 -0
- package/src/response/IMDSBadResponse.ts +9 -0
- package/src/response/ResponseHandler.ts +614 -0
- package/src/response/ServerAuthorizationCodeResponse.ts +33 -0
- package/src/response/ServerAuthorizationTokenResponse.ts +54 -0
- package/src/telemetry/performance/IPerformanceClient.ts +71 -0
- package/src/telemetry/performance/IPerformanceMeasurement.ts +10 -0
- package/src/telemetry/performance/PerformanceClient.ts +635 -0
- package/src/telemetry/performance/PerformanceEvent.ts +542 -0
- package/src/telemetry/performance/StubPerformanceClient.ts +101 -0
- package/src/telemetry/server/ServerTelemetryManager.ts +274 -0
- package/src/telemetry/server/ServerTelemetryRequest.ts +13 -0
- package/src/url/IUri.ts +17 -0
- package/src/url/UrlString.ts +363 -0
- package/src/utils/Constants.ts +436 -0
- package/src/utils/FunctionWrappers.ts +105 -0
- package/src/utils/MsalTypes.ts +9 -0
- package/src/utils/ProtocolUtils.ts +124 -0
- package/src/utils/StringUtils.ts +106 -0
- package/src/utils/TimeUtils.ts +51 -0
- package/dist/account/DecodedAuthToken.d.ts +0 -9
- package/dist/account/DecodedAuthToken.d.ts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @azure/msal-common v14.0.
|
|
1
|
+
/*! @azure/msal-common v14.0.3 2023-09-05 */
|
|
2
2
|
'use strict';
|
|
3
3
|
'use strict';
|
|
4
4
|
|
|
@@ -65,6 +65,15 @@ const Constants = {
|
|
|
65
65
|
SHR_NONCE_VALIDITY: 240,
|
|
66
66
|
INVALID_INSTANCE: "invalid_instance",
|
|
67
67
|
};
|
|
68
|
+
const HttpStatus = {
|
|
69
|
+
SUCCESS_RANGE_START: 200,
|
|
70
|
+
SUCCESS_RANGE_END: 299,
|
|
71
|
+
REDIRECT: 302,
|
|
72
|
+
CLIENT_ERROR_RANGE_START: 400,
|
|
73
|
+
CLIENT_ERROR_RANGE_END: 499,
|
|
74
|
+
SERVER_ERROR_RANGE_START: 500,
|
|
75
|
+
SERVER_ERROR_RANGE_END: 599,
|
|
76
|
+
};
|
|
68
77
|
const OIDC_DEFAULT_SCOPES = [
|
|
69
78
|
Constants.OPENID_SCOPE,
|
|
70
79
|
Constants.PROFILE_SCOPE,
|
|
@@ -457,6 +466,218 @@ const DEFAULT_CRYPTO_IMPLEMENTATION = {
|
|
|
457
466
|
},
|
|
458
467
|
};
|
|
459
468
|
|
|
469
|
+
/*
|
|
470
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
471
|
+
* Licensed under the MIT License.
|
|
472
|
+
*/
|
|
473
|
+
/**
|
|
474
|
+
* Log message level.
|
|
475
|
+
*/
|
|
476
|
+
exports.LogLevel = void 0;
|
|
477
|
+
(function (LogLevel) {
|
|
478
|
+
LogLevel[LogLevel["Error"] = 0] = "Error";
|
|
479
|
+
LogLevel[LogLevel["Warning"] = 1] = "Warning";
|
|
480
|
+
LogLevel[LogLevel["Info"] = 2] = "Info";
|
|
481
|
+
LogLevel[LogLevel["Verbose"] = 3] = "Verbose";
|
|
482
|
+
LogLevel[LogLevel["Trace"] = 4] = "Trace";
|
|
483
|
+
})(exports.LogLevel || (exports.LogLevel = {}));
|
|
484
|
+
/**
|
|
485
|
+
* Class which facilitates logging of messages to a specific place.
|
|
486
|
+
*/
|
|
487
|
+
class Logger {
|
|
488
|
+
constructor(loggerOptions, packageName, packageVersion) {
|
|
489
|
+
// Current log level, defaults to info.
|
|
490
|
+
this.level = exports.LogLevel.Info;
|
|
491
|
+
const defaultLoggerCallback = () => {
|
|
492
|
+
return;
|
|
493
|
+
};
|
|
494
|
+
const setLoggerOptions = loggerOptions || Logger.createDefaultLoggerOptions();
|
|
495
|
+
this.localCallback =
|
|
496
|
+
setLoggerOptions.loggerCallback || defaultLoggerCallback;
|
|
497
|
+
this.piiLoggingEnabled = setLoggerOptions.piiLoggingEnabled || false;
|
|
498
|
+
this.level =
|
|
499
|
+
typeof setLoggerOptions.logLevel === "number"
|
|
500
|
+
? setLoggerOptions.logLevel
|
|
501
|
+
: exports.LogLevel.Info;
|
|
502
|
+
this.correlationId =
|
|
503
|
+
setLoggerOptions.correlationId || Constants.EMPTY_STRING;
|
|
504
|
+
this.packageName = packageName || Constants.EMPTY_STRING;
|
|
505
|
+
this.packageVersion = packageVersion || Constants.EMPTY_STRING;
|
|
506
|
+
}
|
|
507
|
+
static createDefaultLoggerOptions() {
|
|
508
|
+
return {
|
|
509
|
+
loggerCallback: () => {
|
|
510
|
+
// allow users to not set loggerCallback
|
|
511
|
+
},
|
|
512
|
+
piiLoggingEnabled: false,
|
|
513
|
+
logLevel: exports.LogLevel.Info,
|
|
514
|
+
};
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* Create new Logger with existing configurations.
|
|
518
|
+
*/
|
|
519
|
+
clone(packageName, packageVersion, correlationId) {
|
|
520
|
+
return new Logger({
|
|
521
|
+
loggerCallback: this.localCallback,
|
|
522
|
+
piiLoggingEnabled: this.piiLoggingEnabled,
|
|
523
|
+
logLevel: this.level,
|
|
524
|
+
correlationId: correlationId || this.correlationId,
|
|
525
|
+
}, packageName, packageVersion);
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* Log message with required options.
|
|
529
|
+
*/
|
|
530
|
+
logMessage(logMessage, options) {
|
|
531
|
+
if (options.logLevel > this.level ||
|
|
532
|
+
(!this.piiLoggingEnabled && options.containsPii)) {
|
|
533
|
+
return;
|
|
534
|
+
}
|
|
535
|
+
const timestamp = new Date().toUTCString();
|
|
536
|
+
// Add correlationId to logs if set, correlationId provided on log messages take precedence
|
|
537
|
+
const logHeader = `[${timestamp}] : [${options.correlationId || this.correlationId || ""}]`;
|
|
538
|
+
const log = `${logHeader} : ${this.packageName}@${this.packageVersion} : ${exports.LogLevel[options.logLevel]} - ${logMessage}`;
|
|
539
|
+
// debug(`msal:${LogLevel[options.logLevel]}${options.containsPii ? "-Pii": Constants.EMPTY_STRING}${options.context ? `:${options.context}` : Constants.EMPTY_STRING}`)(logMessage);
|
|
540
|
+
this.executeCallback(options.logLevel, log, options.containsPii || false);
|
|
541
|
+
}
|
|
542
|
+
/**
|
|
543
|
+
* Execute callback with message.
|
|
544
|
+
*/
|
|
545
|
+
executeCallback(level, message, containsPii) {
|
|
546
|
+
if (this.localCallback) {
|
|
547
|
+
this.localCallback(level, message, containsPii);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
/**
|
|
551
|
+
* Logs error messages.
|
|
552
|
+
*/
|
|
553
|
+
error(message, correlationId) {
|
|
554
|
+
this.logMessage(message, {
|
|
555
|
+
logLevel: exports.LogLevel.Error,
|
|
556
|
+
containsPii: false,
|
|
557
|
+
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
/**
|
|
561
|
+
* Logs error messages with PII.
|
|
562
|
+
*/
|
|
563
|
+
errorPii(message, correlationId) {
|
|
564
|
+
this.logMessage(message, {
|
|
565
|
+
logLevel: exports.LogLevel.Error,
|
|
566
|
+
containsPii: true,
|
|
567
|
+
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Logs warning messages.
|
|
572
|
+
*/
|
|
573
|
+
warning(message, correlationId) {
|
|
574
|
+
this.logMessage(message, {
|
|
575
|
+
logLevel: exports.LogLevel.Warning,
|
|
576
|
+
containsPii: false,
|
|
577
|
+
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
578
|
+
});
|
|
579
|
+
}
|
|
580
|
+
/**
|
|
581
|
+
* Logs warning messages with PII.
|
|
582
|
+
*/
|
|
583
|
+
warningPii(message, correlationId) {
|
|
584
|
+
this.logMessage(message, {
|
|
585
|
+
logLevel: exports.LogLevel.Warning,
|
|
586
|
+
containsPii: true,
|
|
587
|
+
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
588
|
+
});
|
|
589
|
+
}
|
|
590
|
+
/**
|
|
591
|
+
* Logs info messages.
|
|
592
|
+
*/
|
|
593
|
+
info(message, correlationId) {
|
|
594
|
+
this.logMessage(message, {
|
|
595
|
+
logLevel: exports.LogLevel.Info,
|
|
596
|
+
containsPii: false,
|
|
597
|
+
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
598
|
+
});
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Logs info messages with PII.
|
|
602
|
+
*/
|
|
603
|
+
infoPii(message, correlationId) {
|
|
604
|
+
this.logMessage(message, {
|
|
605
|
+
logLevel: exports.LogLevel.Info,
|
|
606
|
+
containsPii: true,
|
|
607
|
+
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* Logs verbose messages.
|
|
612
|
+
*/
|
|
613
|
+
verbose(message, correlationId) {
|
|
614
|
+
this.logMessage(message, {
|
|
615
|
+
logLevel: exports.LogLevel.Verbose,
|
|
616
|
+
containsPii: false,
|
|
617
|
+
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
/**
|
|
621
|
+
* Logs verbose messages with PII.
|
|
622
|
+
*/
|
|
623
|
+
verbosePii(message, correlationId) {
|
|
624
|
+
this.logMessage(message, {
|
|
625
|
+
logLevel: exports.LogLevel.Verbose,
|
|
626
|
+
containsPii: true,
|
|
627
|
+
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
/**
|
|
631
|
+
* Logs trace messages.
|
|
632
|
+
*/
|
|
633
|
+
trace(message, correlationId) {
|
|
634
|
+
this.logMessage(message, {
|
|
635
|
+
logLevel: exports.LogLevel.Trace,
|
|
636
|
+
containsPii: false,
|
|
637
|
+
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Logs trace messages with PII.
|
|
642
|
+
*/
|
|
643
|
+
tracePii(message, correlationId) {
|
|
644
|
+
this.logMessage(message, {
|
|
645
|
+
logLevel: exports.LogLevel.Trace,
|
|
646
|
+
containsPii: true,
|
|
647
|
+
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
/**
|
|
651
|
+
* Returns whether PII Logging is enabled or not.
|
|
652
|
+
*/
|
|
653
|
+
isPiiLoggingEnabled() {
|
|
654
|
+
return this.piiLoggingEnabled || false;
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
/* eslint-disable header/header */
|
|
659
|
+
const name = "@azure/msal-common";
|
|
660
|
+
const version = "14.0.3";
|
|
661
|
+
|
|
662
|
+
/*
|
|
663
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
664
|
+
* Licensed under the MIT License.
|
|
665
|
+
*/
|
|
666
|
+
const AzureCloudInstance = {
|
|
667
|
+
// AzureCloudInstance is not specified.
|
|
668
|
+
None: "none",
|
|
669
|
+
// Microsoft Azure public cloud
|
|
670
|
+
AzurePublic: "https://login.microsoftonline.com",
|
|
671
|
+
// Microsoft PPE
|
|
672
|
+
AzurePpe: "https://login.windows-ppe.net",
|
|
673
|
+
// Microsoft Chinese national/regional cloud
|
|
674
|
+
AzureChina: "https://login.chinacloudapi.cn",
|
|
675
|
+
// Microsoft German national/regional cloud ("Black Forest")
|
|
676
|
+
AzureGermany: "https://login.microsoftonline.de",
|
|
677
|
+
// US Government cloud
|
|
678
|
+
AzureUsGovernment: "https://login.microsoftonline.us",
|
|
679
|
+
};
|
|
680
|
+
|
|
460
681
|
/*
|
|
461
682
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
462
683
|
* Licensed under the MIT License.
|
|
@@ -982,765 +1203,515 @@ class ClientAuthError extends AuthError {
|
|
|
982
1203
|
* Licensed under the MIT License.
|
|
983
1204
|
*/
|
|
984
1205
|
/**
|
|
985
|
-
*
|
|
1206
|
+
* ClientConfigurationErrorMessage class containing string constants used by error codes and messages.
|
|
986
1207
|
*/
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1208
|
+
const ClientConfigurationErrorMessage = {
|
|
1209
|
+
redirectUriNotSet: {
|
|
1210
|
+
code: "redirect_uri_empty",
|
|
1211
|
+
desc: "A redirect URI is required for all calls, and none has been set.",
|
|
1212
|
+
},
|
|
1213
|
+
postLogoutUriNotSet: {
|
|
1214
|
+
code: "post_logout_uri_empty",
|
|
1215
|
+
desc: "A post logout redirect has not been set.",
|
|
1216
|
+
},
|
|
1217
|
+
claimsRequestParsingError: {
|
|
1218
|
+
code: "claims_request_parsing_error",
|
|
1219
|
+
desc: "Could not parse the given claims request object.",
|
|
1220
|
+
},
|
|
1221
|
+
authorityUriInsecure: {
|
|
1222
|
+
code: "authority_uri_insecure",
|
|
1223
|
+
desc: "Authority URIs must use https. Please see here for valid authority configuration options: https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-js-initializing-client-applications#configuration-options",
|
|
1224
|
+
},
|
|
1225
|
+
urlParseError: {
|
|
1226
|
+
code: "url_parse_error",
|
|
1227
|
+
desc: "URL could not be parsed into appropriate segments.",
|
|
1228
|
+
},
|
|
1229
|
+
urlEmptyError: {
|
|
1230
|
+
code: "empty_url_error",
|
|
1231
|
+
desc: "URL was empty or null.",
|
|
1232
|
+
},
|
|
1233
|
+
emptyScopesError: {
|
|
1234
|
+
code: "empty_input_scopes_error",
|
|
1235
|
+
desc: "Scopes cannot be passed as null, undefined or empty array because they are required to obtain an access token.",
|
|
1236
|
+
},
|
|
1237
|
+
nonArrayScopesError: {
|
|
1238
|
+
code: "nonarray_input_scopes_error",
|
|
1239
|
+
desc: "Scopes cannot be passed as non-array.",
|
|
1240
|
+
},
|
|
1241
|
+
clientIdSingleScopeError: {
|
|
1242
|
+
code: "clientid_input_scopes_error",
|
|
1243
|
+
desc: "Client ID can only be provided as a single scope.",
|
|
1244
|
+
},
|
|
1245
|
+
invalidPrompt: {
|
|
1246
|
+
code: "invalid_prompt_value",
|
|
1247
|
+
desc: "Supported prompt values are 'login', 'select_account', 'consent', 'create', 'none' and 'no_session'. Please see here for valid configuration options: https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_common.html#commonauthorizationurlrequest",
|
|
1248
|
+
},
|
|
1249
|
+
invalidClaimsRequest: {
|
|
1250
|
+
code: "invalid_claims",
|
|
1251
|
+
desc: "Given claims parameter must be a stringified JSON object.",
|
|
1252
|
+
},
|
|
1253
|
+
tokenRequestEmptyError: {
|
|
1254
|
+
code: "token_request_empty",
|
|
1255
|
+
desc: "Token request was empty and not found in cache.",
|
|
1256
|
+
},
|
|
1257
|
+
logoutRequestEmptyError: {
|
|
1258
|
+
code: "logout_request_empty",
|
|
1259
|
+
desc: "The logout request was null or undefined.",
|
|
1260
|
+
},
|
|
1261
|
+
invalidCodeChallengeMethod: {
|
|
1262
|
+
code: "invalid_code_challenge_method",
|
|
1263
|
+
desc: 'code_challenge_method passed is invalid. Valid values are "plain" and "S256".',
|
|
1264
|
+
},
|
|
1265
|
+
invalidCodeChallengeParams: {
|
|
1266
|
+
code: "pkce_params_missing",
|
|
1267
|
+
desc: "Both params: code_challenge and code_challenge_method are to be passed if to be sent in the request",
|
|
1268
|
+
},
|
|
1269
|
+
invalidCloudDiscoveryMetadata: {
|
|
1270
|
+
code: "invalid_cloud_discovery_metadata",
|
|
1271
|
+
desc: "Invalid cloudDiscoveryMetadata provided. Must be a stringified JSON object containing tenant_discovery_endpoint and metadata fields",
|
|
1272
|
+
},
|
|
1273
|
+
invalidAuthorityMetadata: {
|
|
1274
|
+
code: "invalid_authority_metadata",
|
|
1275
|
+
desc: "Invalid authorityMetadata provided. Must by a stringified JSON object containing authorization_endpoint, token_endpoint, issuer fields.",
|
|
1276
|
+
},
|
|
1277
|
+
untrustedAuthority: {
|
|
1278
|
+
code: "untrusted_authority",
|
|
1279
|
+
desc: "The provided authority is not a trusted authority. Please include this authority in the knownAuthorities config parameter.",
|
|
1280
|
+
},
|
|
1281
|
+
invalidAzureCloudInstance: {
|
|
1282
|
+
code: "invalid_azure_cloud_instance",
|
|
1283
|
+
desc: "Invalid AzureCloudInstance provided. Please refer MSAL JS docs: aks.ms/msaljs/azure_cloud_instance for valid values",
|
|
1284
|
+
},
|
|
1285
|
+
missingSshJwk: {
|
|
1286
|
+
code: "missing_ssh_jwk",
|
|
1287
|
+
desc: "Missing sshJwk in SSH certificate request. A stringified JSON Web Key is required when using the SSH authentication scheme.",
|
|
1288
|
+
},
|
|
1289
|
+
missingSshKid: {
|
|
1290
|
+
code: "missing_ssh_kid",
|
|
1291
|
+
desc: "Missing sshKid in SSH certificate request. A string that uniquely identifies the public SSH key is required when using the SSH authentication scheme.",
|
|
1292
|
+
},
|
|
1293
|
+
missingNonceAuthenticationHeader: {
|
|
1294
|
+
code: "missing_nonce_authentication_header",
|
|
1295
|
+
desc: "Unable to find an authentication header containing server nonce. Either the Authentication-Info or WWW-Authenticate headers must be present in order to obtain a server nonce.",
|
|
1296
|
+
},
|
|
1297
|
+
invalidAuthenticationHeader: {
|
|
1298
|
+
code: "invalid_authentication_header",
|
|
1299
|
+
desc: "Invalid authentication header provided",
|
|
1300
|
+
},
|
|
1301
|
+
cannotSetOIDCOptions: {
|
|
1302
|
+
code: "cannot_set_OIDCOptions",
|
|
1303
|
+
desc: "Cannot set OIDCOptions parameter. Please change the protocol mode to OIDC or use a non-Microsoft authority.",
|
|
1304
|
+
},
|
|
1305
|
+
cannotAllowNativeBroker: {
|
|
1306
|
+
code: "cannot_allow_native_broker",
|
|
1307
|
+
desc: "Cannot set allowNativeBroker parameter to true when not in AAD protocol mode.",
|
|
1308
|
+
},
|
|
1309
|
+
authorityMismatch: {
|
|
1310
|
+
code: "authority_mismatch",
|
|
1311
|
+
desc: "Authority mismatch error. Authority provided in login request or PublicClientApplication config does not match the environment of the provided account. Please use a matching account or make an interactive request to login to this authority.",
|
|
1312
|
+
},
|
|
1313
|
+
};
|
|
1314
|
+
/**
|
|
1315
|
+
* Error thrown when there is an error in configuration of the MSAL.js library.
|
|
1316
|
+
*/
|
|
1317
|
+
class ClientConfigurationError extends ClientAuthError {
|
|
1318
|
+
constructor(errorCode, errorMessage) {
|
|
1319
|
+
super(errorCode, errorMessage);
|
|
1320
|
+
this.name = "ClientConfigurationError";
|
|
1321
|
+
Object.setPrototypeOf(this, ClientConfigurationError.prototype);
|
|
1056
1322
|
}
|
|
1057
1323
|
/**
|
|
1058
|
-
*
|
|
1059
|
-
*
|
|
1060
|
-
* @param arr
|
|
1324
|
+
* Creates an error thrown when the redirect uri is empty (not set by caller)
|
|
1061
1325
|
*/
|
|
1062
|
-
static
|
|
1063
|
-
return
|
|
1326
|
+
static createRedirectUriEmptyError() {
|
|
1327
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.redirectUriNotSet.code, ClientConfigurationErrorMessage.redirectUriNotSet.desc);
|
|
1064
1328
|
}
|
|
1065
1329
|
/**
|
|
1066
|
-
*
|
|
1067
|
-
* @param arr
|
|
1330
|
+
* Creates an error thrown when the post-logout redirect uri is empty (not set by caller)
|
|
1068
1331
|
*/
|
|
1069
|
-
static
|
|
1070
|
-
return
|
|
1071
|
-
return !StringUtils.isEmpty(entry);
|
|
1072
|
-
});
|
|
1332
|
+
static createPostLogoutRedirectUriEmptyError() {
|
|
1333
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.postLogoutUriNotSet.code, ClientConfigurationErrorMessage.postLogoutUriNotSet.desc);
|
|
1073
1334
|
}
|
|
1074
1335
|
/**
|
|
1075
|
-
*
|
|
1076
|
-
* @param str
|
|
1336
|
+
* Creates an error thrown when the claims request could not be successfully parsed
|
|
1077
1337
|
*/
|
|
1078
|
-
static
|
|
1079
|
-
|
|
1080
|
-
return JSON.parse(str);
|
|
1081
|
-
}
|
|
1082
|
-
catch (e) {
|
|
1083
|
-
return null;
|
|
1084
|
-
}
|
|
1338
|
+
static createClaimsRequestParsingError(claimsRequestParseError) {
|
|
1339
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.claimsRequestParsingError.code, `${ClientConfigurationErrorMessage.claimsRequestParsingError.desc} Given value: ${claimsRequestParseError}`);
|
|
1085
1340
|
}
|
|
1086
1341
|
/**
|
|
1087
|
-
*
|
|
1088
|
-
* @param
|
|
1089
|
-
* @param input String to match against
|
|
1342
|
+
* Creates an error thrown if authority uri is given an insecure protocol.
|
|
1343
|
+
* @param urlString
|
|
1090
1344
|
*/
|
|
1091
|
-
static
|
|
1092
|
-
|
|
1093
|
-
* Wildcard support: https://stackoverflow.com/a/3117248/4888559
|
|
1094
|
-
* Queries: replaces "?" in string with escaped "\?" for regex test
|
|
1095
|
-
*/
|
|
1096
|
-
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
1097
|
-
const regex = new RegExp(pattern
|
|
1098
|
-
.replace(/\\/g, "\\\\")
|
|
1099
|
-
.replace(/\*/g, "[^ ]*")
|
|
1100
|
-
.replace(/\?/g, "\\?"));
|
|
1101
|
-
return regex.test(input);
|
|
1102
|
-
}
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
/*
|
|
1106
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
1107
|
-
* Licensed under the MIT License.
|
|
1108
|
-
*/
|
|
1109
|
-
/**
|
|
1110
|
-
* Log message level.
|
|
1111
|
-
*/
|
|
1112
|
-
exports.LogLevel = void 0;
|
|
1113
|
-
(function (LogLevel) {
|
|
1114
|
-
LogLevel[LogLevel["Error"] = 0] = "Error";
|
|
1115
|
-
LogLevel[LogLevel["Warning"] = 1] = "Warning";
|
|
1116
|
-
LogLevel[LogLevel["Info"] = 2] = "Info";
|
|
1117
|
-
LogLevel[LogLevel["Verbose"] = 3] = "Verbose";
|
|
1118
|
-
LogLevel[LogLevel["Trace"] = 4] = "Trace";
|
|
1119
|
-
})(exports.LogLevel || (exports.LogLevel = {}));
|
|
1120
|
-
/**
|
|
1121
|
-
* Class which facilitates logging of messages to a specific place.
|
|
1122
|
-
*/
|
|
1123
|
-
class Logger {
|
|
1124
|
-
constructor(loggerOptions, packageName, packageVersion) {
|
|
1125
|
-
// Current log level, defaults to info.
|
|
1126
|
-
this.level = exports.LogLevel.Info;
|
|
1127
|
-
const defaultLoggerCallback = () => {
|
|
1128
|
-
return;
|
|
1129
|
-
};
|
|
1130
|
-
const setLoggerOptions = loggerOptions || Logger.createDefaultLoggerOptions();
|
|
1131
|
-
this.localCallback =
|
|
1132
|
-
setLoggerOptions.loggerCallback || defaultLoggerCallback;
|
|
1133
|
-
this.piiLoggingEnabled = setLoggerOptions.piiLoggingEnabled || false;
|
|
1134
|
-
this.level =
|
|
1135
|
-
typeof setLoggerOptions.logLevel === "number"
|
|
1136
|
-
? setLoggerOptions.logLevel
|
|
1137
|
-
: exports.LogLevel.Info;
|
|
1138
|
-
this.correlationId =
|
|
1139
|
-
setLoggerOptions.correlationId || Constants.EMPTY_STRING;
|
|
1140
|
-
this.packageName = packageName || Constants.EMPTY_STRING;
|
|
1141
|
-
this.packageVersion = packageVersion || Constants.EMPTY_STRING;
|
|
1345
|
+
static createInsecureAuthorityUriError(urlString) {
|
|
1346
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.authorityUriInsecure.code, `${ClientConfigurationErrorMessage.authorityUriInsecure.desc} Given URI: ${urlString}`);
|
|
1142
1347
|
}
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
logLevel: exports.LogLevel.Info,
|
|
1150
|
-
};
|
|
1348
|
+
/**
|
|
1349
|
+
* Creates an error thrown if URL string does not parse into separate segments.
|
|
1350
|
+
* @param urlString
|
|
1351
|
+
*/
|
|
1352
|
+
static createUrlParseError(urlParseError) {
|
|
1353
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.urlParseError.code, `${ClientConfigurationErrorMessage.urlParseError.desc} Given Error: ${urlParseError}`);
|
|
1151
1354
|
}
|
|
1152
1355
|
/**
|
|
1153
|
-
*
|
|
1356
|
+
* Creates an error thrown if URL string is empty or null.
|
|
1357
|
+
* @param urlString
|
|
1154
1358
|
*/
|
|
1155
|
-
|
|
1156
|
-
return new
|
|
1157
|
-
loggerCallback: this.localCallback,
|
|
1158
|
-
piiLoggingEnabled: this.piiLoggingEnabled,
|
|
1159
|
-
logLevel: this.level,
|
|
1160
|
-
correlationId: correlationId || this.correlationId,
|
|
1161
|
-
}, packageName, packageVersion);
|
|
1359
|
+
static createUrlEmptyError() {
|
|
1360
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.urlEmptyError.code, ClientConfigurationErrorMessage.urlEmptyError.desc);
|
|
1162
1361
|
}
|
|
1163
1362
|
/**
|
|
1164
|
-
*
|
|
1363
|
+
* Error thrown when scopes are empty.
|
|
1364
|
+
* @param scopesValue
|
|
1165
1365
|
*/
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
(!this.piiLoggingEnabled && options.containsPii)) {
|
|
1169
|
-
return;
|
|
1170
|
-
}
|
|
1171
|
-
const timestamp = new Date().toUTCString();
|
|
1172
|
-
// Add correlationId to logs if set, correlationId provided on log messages take precedence
|
|
1173
|
-
let logHeader;
|
|
1174
|
-
if (!StringUtils.isEmpty(options.correlationId)) {
|
|
1175
|
-
logHeader = `[${timestamp}] : [${options.correlationId}]`;
|
|
1176
|
-
}
|
|
1177
|
-
else if (!StringUtils.isEmpty(this.correlationId)) {
|
|
1178
|
-
logHeader = `[${timestamp}] : [${this.correlationId}]`;
|
|
1179
|
-
}
|
|
1180
|
-
else {
|
|
1181
|
-
logHeader = `[${timestamp}]`;
|
|
1182
|
-
}
|
|
1183
|
-
const log = `${logHeader} : ${this.packageName}@${this.packageVersion} : ${exports.LogLevel[options.logLevel]} - ${logMessage}`;
|
|
1184
|
-
// debug(`msal:${LogLevel[options.logLevel]}${options.containsPii ? "-Pii": Constants.EMPTY_STRING}${options.context ? `:${options.context}` : Constants.EMPTY_STRING}`)(logMessage);
|
|
1185
|
-
this.executeCallback(options.logLevel, log, options.containsPii || false);
|
|
1366
|
+
static createEmptyScopesArrayError() {
|
|
1367
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.emptyScopesError.code, `${ClientConfigurationErrorMessage.emptyScopesError.desc}`);
|
|
1186
1368
|
}
|
|
1187
1369
|
/**
|
|
1188
|
-
*
|
|
1370
|
+
* Error thrown when client id scope is not provided as single scope.
|
|
1371
|
+
* @param inputScopes
|
|
1189
1372
|
*/
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
this.localCallback(level, message, containsPii);
|
|
1193
|
-
}
|
|
1373
|
+
static createClientIdSingleScopeError(inputScopes) {
|
|
1374
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.clientIdSingleScopeError.code, `${ClientConfigurationErrorMessage.clientIdSingleScopeError.desc} Given Scopes: ${inputScopes}`);
|
|
1194
1375
|
}
|
|
1195
1376
|
/**
|
|
1196
|
-
*
|
|
1377
|
+
* Error thrown when prompt is not an allowed type.
|
|
1378
|
+
* @param promptValue
|
|
1197
1379
|
*/
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
logLevel: exports.LogLevel.Error,
|
|
1201
|
-
containsPii: false,
|
|
1202
|
-
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
1203
|
-
});
|
|
1380
|
+
static createInvalidPromptError(promptValue) {
|
|
1381
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidPrompt.code, `${ClientConfigurationErrorMessage.invalidPrompt.desc} Given value: ${promptValue}`);
|
|
1204
1382
|
}
|
|
1205
1383
|
/**
|
|
1206
|
-
*
|
|
1384
|
+
* Creates error thrown when claims parameter is not a stringified JSON object
|
|
1207
1385
|
*/
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
logLevel: exports.LogLevel.Error,
|
|
1211
|
-
containsPii: true,
|
|
1212
|
-
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
1213
|
-
});
|
|
1386
|
+
static createInvalidClaimsRequestError() {
|
|
1387
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidClaimsRequest.code, ClientConfigurationErrorMessage.invalidClaimsRequest.desc);
|
|
1214
1388
|
}
|
|
1215
1389
|
/**
|
|
1216
|
-
*
|
|
1390
|
+
* Throws error when token request is empty and nothing cached in storage.
|
|
1217
1391
|
*/
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
logLevel: exports.LogLevel.Warning,
|
|
1221
|
-
containsPii: false,
|
|
1222
|
-
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
1223
|
-
});
|
|
1392
|
+
static createEmptyLogoutRequestError() {
|
|
1393
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.logoutRequestEmptyError.code, ClientConfigurationErrorMessage.logoutRequestEmptyError.desc);
|
|
1224
1394
|
}
|
|
1225
1395
|
/**
|
|
1226
|
-
*
|
|
1396
|
+
* Throws error when token request is empty and nothing cached in storage.
|
|
1227
1397
|
*/
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
logLevel: exports.LogLevel.Warning,
|
|
1231
|
-
containsPii: true,
|
|
1232
|
-
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
1233
|
-
});
|
|
1398
|
+
static createEmptyTokenRequestError() {
|
|
1399
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.tokenRequestEmptyError.code, ClientConfigurationErrorMessage.tokenRequestEmptyError.desc);
|
|
1234
1400
|
}
|
|
1235
1401
|
/**
|
|
1236
|
-
*
|
|
1402
|
+
* Throws error when an invalid code_challenge_method is passed by the user
|
|
1237
1403
|
*/
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
logLevel: exports.LogLevel.Info,
|
|
1241
|
-
containsPii: false,
|
|
1242
|
-
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
1243
|
-
});
|
|
1404
|
+
static createInvalidCodeChallengeMethodError() {
|
|
1405
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCodeChallengeMethod.code, ClientConfigurationErrorMessage.invalidCodeChallengeMethod.desc);
|
|
1244
1406
|
}
|
|
1245
1407
|
/**
|
|
1246
|
-
*
|
|
1408
|
+
* Throws error when both params: code_challenge and code_challenge_method are not passed together
|
|
1247
1409
|
*/
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
logLevel: exports.LogLevel.Info,
|
|
1251
|
-
containsPii: true,
|
|
1252
|
-
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
1253
|
-
});
|
|
1410
|
+
static createInvalidCodeChallengeParamsError() {
|
|
1411
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCodeChallengeParams.code, ClientConfigurationErrorMessage.invalidCodeChallengeParams.desc);
|
|
1254
1412
|
}
|
|
1255
1413
|
/**
|
|
1256
|
-
*
|
|
1414
|
+
* Throws an error when the user passes invalid cloudDiscoveryMetadata
|
|
1257
1415
|
*/
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
logLevel: exports.LogLevel.Verbose,
|
|
1261
|
-
containsPii: false,
|
|
1262
|
-
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
1263
|
-
});
|
|
1416
|
+
static createInvalidCloudDiscoveryMetadataError() {
|
|
1417
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCloudDiscoveryMetadata.code, ClientConfigurationErrorMessage.invalidCloudDiscoveryMetadata.desc);
|
|
1264
1418
|
}
|
|
1265
1419
|
/**
|
|
1266
|
-
*
|
|
1420
|
+
* Throws an error when the user passes invalid cloudDiscoveryMetadata
|
|
1267
1421
|
*/
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
logLevel: exports.LogLevel.Verbose,
|
|
1271
|
-
containsPii: true,
|
|
1272
|
-
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
1273
|
-
});
|
|
1422
|
+
static createInvalidAuthorityMetadataError() {
|
|
1423
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidAuthorityMetadata.code, ClientConfigurationErrorMessage.invalidAuthorityMetadata.desc);
|
|
1274
1424
|
}
|
|
1275
1425
|
/**
|
|
1276
|
-
*
|
|
1426
|
+
* Throws error when provided authority is not a member of the trusted host list
|
|
1277
1427
|
*/
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
logLevel: exports.LogLevel.Trace,
|
|
1281
|
-
containsPii: false,
|
|
1282
|
-
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
1283
|
-
});
|
|
1428
|
+
static createUntrustedAuthorityError() {
|
|
1429
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.untrustedAuthority.code, ClientConfigurationErrorMessage.untrustedAuthority.desc);
|
|
1284
1430
|
}
|
|
1285
1431
|
/**
|
|
1286
|
-
*
|
|
1432
|
+
* Throws error when the AzureCloudInstance is set to an invalid value
|
|
1287
1433
|
*/
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
logLevel: exports.LogLevel.Trace,
|
|
1291
|
-
containsPii: true,
|
|
1292
|
-
correlationId: correlationId || Constants.EMPTY_STRING,
|
|
1293
|
-
});
|
|
1434
|
+
static createInvalidAzureCloudInstanceError() {
|
|
1435
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidAzureCloudInstance.code, ClientConfigurationErrorMessage.invalidAzureCloudInstance.desc);
|
|
1294
1436
|
}
|
|
1295
1437
|
/**
|
|
1296
|
-
*
|
|
1438
|
+
* Throws an error when the authentication scheme is set to SSH but the SSH public key is omitted from the request
|
|
1297
1439
|
*/
|
|
1298
|
-
|
|
1299
|
-
return
|
|
1440
|
+
static createMissingSshJwkError() {
|
|
1441
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.missingSshJwk.code, ClientConfigurationErrorMessage.missingSshJwk.desc);
|
|
1442
|
+
}
|
|
1443
|
+
/**
|
|
1444
|
+
* Throws an error when the authentication scheme is set to SSH but the SSH public key ID is omitted from the request
|
|
1445
|
+
*/
|
|
1446
|
+
static createMissingSshKidError() {
|
|
1447
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.missingSshKid.code, ClientConfigurationErrorMessage.missingSshKid.desc);
|
|
1448
|
+
}
|
|
1449
|
+
/**
|
|
1450
|
+
* Throws error when provided headers don't contain a header that a server nonce can be extracted from
|
|
1451
|
+
*/
|
|
1452
|
+
static createMissingNonceAuthenticationHeadersError() {
|
|
1453
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.missingNonceAuthenticationHeader.code, ClientConfigurationErrorMessage.missingNonceAuthenticationHeader.desc);
|
|
1454
|
+
}
|
|
1455
|
+
/**
|
|
1456
|
+
* Throws error when a provided header is invalid in any way
|
|
1457
|
+
*/
|
|
1458
|
+
static createInvalidAuthenticationHeaderError(invalidHeaderName, details) {
|
|
1459
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidAuthenticationHeader.code, `${ClientConfigurationErrorMessage.invalidAuthenticationHeader.desc}. Invalid header: ${invalidHeaderName}. Details: ${details}`);
|
|
1460
|
+
}
|
|
1461
|
+
/**
|
|
1462
|
+
* Throws error when provided non-default OIDCOptions when not in OIDC protocol mode
|
|
1463
|
+
*/
|
|
1464
|
+
static createCannotSetOIDCOptionsError() {
|
|
1465
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.cannotSetOIDCOptions.code, ClientConfigurationErrorMessage.cannotSetOIDCOptions.desc);
|
|
1466
|
+
}
|
|
1467
|
+
/**
|
|
1468
|
+
* Throws error when allowNativeBroker is set to true when not in AAD protocol mode
|
|
1469
|
+
*/
|
|
1470
|
+
static createCannotAllowNativeBrokerError() {
|
|
1471
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.cannotAllowNativeBroker.code, ClientConfigurationErrorMessage.cannotAllowNativeBroker.desc);
|
|
1472
|
+
}
|
|
1473
|
+
/**
|
|
1474
|
+
* Create an error when the authority provided in request does not match authority provided in account or MSAL.js configuration.
|
|
1475
|
+
*/
|
|
1476
|
+
static createAuthorityMismatchError() {
|
|
1477
|
+
return new ClientConfigurationError(ClientConfigurationErrorMessage.authorityMismatch.code, ClientConfigurationErrorMessage.authorityMismatch.desc);
|
|
1300
1478
|
}
|
|
1301
1479
|
}
|
|
1302
1480
|
|
|
1303
|
-
/* eslint-disable header/header */
|
|
1304
|
-
const name = "@azure/msal-common";
|
|
1305
|
-
const version = "14.0.2";
|
|
1306
|
-
|
|
1307
1481
|
/*
|
|
1308
1482
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
1309
1483
|
* Licensed under the MIT License.
|
|
1310
1484
|
*/
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
}
|
|
1485
|
+
/**
|
|
1486
|
+
* @hidden
|
|
1487
|
+
*/
|
|
1488
|
+
class StringUtils {
|
|
1489
|
+
/**
|
|
1490
|
+
* Check if stringified object is empty
|
|
1491
|
+
* @param strObj
|
|
1492
|
+
*/
|
|
1493
|
+
static isEmptyObj(strObj) {
|
|
1494
|
+
if (strObj) {
|
|
1495
|
+
try {
|
|
1496
|
+
const obj = JSON.parse(strObj);
|
|
1497
|
+
return Object.keys(obj).length === 0;
|
|
1498
|
+
}
|
|
1499
|
+
catch (e) { }
|
|
1500
|
+
}
|
|
1501
|
+
return true;
|
|
1502
|
+
}
|
|
1503
|
+
static startsWith(str, search) {
|
|
1504
|
+
return str.indexOf(search) === 0;
|
|
1505
|
+
}
|
|
1506
|
+
static endsWith(str, search) {
|
|
1507
|
+
return (str.length >= search.length &&
|
|
1508
|
+
str.lastIndexOf(search) === str.length - search.length);
|
|
1509
|
+
}
|
|
1510
|
+
/**
|
|
1511
|
+
* Parses string into an object.
|
|
1512
|
+
*
|
|
1513
|
+
* @param query
|
|
1514
|
+
*/
|
|
1515
|
+
static queryStringToObject(query) {
|
|
1516
|
+
const obj = {};
|
|
1517
|
+
const params = query.split("&");
|
|
1518
|
+
const decode = (s) => decodeURIComponent(s.replace(/\+/g, " "));
|
|
1519
|
+
params.forEach((pair) => {
|
|
1520
|
+
if (pair.trim()) {
|
|
1521
|
+
const [key, value] = pair.split(/=(.+)/g, 2); // Split on the first occurence of the '=' character
|
|
1522
|
+
if (key && value) {
|
|
1523
|
+
obj[decode(key)] = decode(value);
|
|
1524
|
+
}
|
|
1525
|
+
}
|
|
1526
|
+
});
|
|
1527
|
+
return obj;
|
|
1528
|
+
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Trims entries in an array.
|
|
1531
|
+
*
|
|
1532
|
+
* @param arr
|
|
1533
|
+
*/
|
|
1534
|
+
static trimArrayEntries(arr) {
|
|
1535
|
+
return arr.map((entry) => entry.trim());
|
|
1536
|
+
}
|
|
1537
|
+
/**
|
|
1538
|
+
* Removes empty strings from array
|
|
1539
|
+
* @param arr
|
|
1540
|
+
*/
|
|
1541
|
+
static removeEmptyStringsFromArray(arr) {
|
|
1542
|
+
return arr.filter((entry) => {
|
|
1543
|
+
return !!entry;
|
|
1544
|
+
});
|
|
1545
|
+
}
|
|
1546
|
+
/**
|
|
1547
|
+
* Attempts to parse a string into JSON
|
|
1548
|
+
* @param str
|
|
1549
|
+
*/
|
|
1550
|
+
static jsonParseHelper(str) {
|
|
1551
|
+
try {
|
|
1552
|
+
return JSON.parse(str);
|
|
1553
|
+
}
|
|
1554
|
+
catch (e) {
|
|
1555
|
+
return null;
|
|
1556
|
+
}
|
|
1557
|
+
}
|
|
1558
|
+
/**
|
|
1559
|
+
* Tests if a given string matches a given pattern, with support for wildcards and queries.
|
|
1560
|
+
* @param pattern Wildcard pattern to string match. Supports "*" for wildcards and "?" for queries
|
|
1561
|
+
* @param input String to match against
|
|
1562
|
+
*/
|
|
1563
|
+
static matchPattern(pattern, input) {
|
|
1564
|
+
/**
|
|
1565
|
+
* Wildcard support: https://stackoverflow.com/a/3117248/4888559
|
|
1566
|
+
* Queries: replaces "?" in string with escaped "\?" for regex test
|
|
1567
|
+
*/
|
|
1568
|
+
// eslint-disable-next-line security/detect-non-literal-regexp
|
|
1569
|
+
const regex = new RegExp(pattern
|
|
1570
|
+
.replace(/\\/g, "\\\\")
|
|
1571
|
+
.replace(/\*/g, "[^ ]*")
|
|
1572
|
+
.replace(/\?/g, "\\?"));
|
|
1573
|
+
return regex.test(input);
|
|
1574
|
+
}
|
|
1575
|
+
}
|
|
1325
1576
|
|
|
1326
1577
|
/*
|
|
1327
1578
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
1328
1579
|
* Licensed under the MIT License.
|
|
1329
1580
|
*/
|
|
1330
1581
|
/**
|
|
1331
|
-
*
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
redirectUriNotSet: {
|
|
1335
|
-
code: "redirect_uri_empty",
|
|
1336
|
-
desc: "A redirect URI is required for all calls, and none has been set.",
|
|
1337
|
-
},
|
|
1338
|
-
postLogoutUriNotSet: {
|
|
1339
|
-
code: "post_logout_uri_empty",
|
|
1340
|
-
desc: "A post logout redirect has not been set.",
|
|
1341
|
-
},
|
|
1342
|
-
claimsRequestParsingError: {
|
|
1343
|
-
code: "claims_request_parsing_error",
|
|
1344
|
-
desc: "Could not parse the given claims request object.",
|
|
1345
|
-
},
|
|
1346
|
-
authorityUriInsecure: {
|
|
1347
|
-
code: "authority_uri_insecure",
|
|
1348
|
-
desc: "Authority URIs must use https. Please see here for valid authority configuration options: https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-js-initializing-client-applications#configuration-options",
|
|
1349
|
-
},
|
|
1350
|
-
urlParseError: {
|
|
1351
|
-
code: "url_parse_error",
|
|
1352
|
-
desc: "URL could not be parsed into appropriate segments.",
|
|
1353
|
-
},
|
|
1354
|
-
urlEmptyError: {
|
|
1355
|
-
code: "empty_url_error",
|
|
1356
|
-
desc: "URL was empty or null.",
|
|
1357
|
-
},
|
|
1358
|
-
emptyScopesError: {
|
|
1359
|
-
code: "empty_input_scopes_error",
|
|
1360
|
-
desc: "Scopes cannot be passed as null, undefined or empty array because they are required to obtain an access token.",
|
|
1361
|
-
},
|
|
1362
|
-
nonArrayScopesError: {
|
|
1363
|
-
code: "nonarray_input_scopes_error",
|
|
1364
|
-
desc: "Scopes cannot be passed as non-array.",
|
|
1365
|
-
},
|
|
1366
|
-
clientIdSingleScopeError: {
|
|
1367
|
-
code: "clientid_input_scopes_error",
|
|
1368
|
-
desc: "Client ID can only be provided as a single scope.",
|
|
1369
|
-
},
|
|
1370
|
-
invalidPrompt: {
|
|
1371
|
-
code: "invalid_prompt_value",
|
|
1372
|
-
desc: "Supported prompt values are 'login', 'select_account', 'consent', 'create', 'none' and 'no_session'. Please see here for valid configuration options: https://azuread.github.io/microsoft-authentication-library-for-js/ref/modules/_azure_msal_common.html#commonauthorizationurlrequest",
|
|
1373
|
-
},
|
|
1374
|
-
invalidClaimsRequest: {
|
|
1375
|
-
code: "invalid_claims",
|
|
1376
|
-
desc: "Given claims parameter must be a stringified JSON object.",
|
|
1377
|
-
},
|
|
1378
|
-
tokenRequestEmptyError: {
|
|
1379
|
-
code: "token_request_empty",
|
|
1380
|
-
desc: "Token request was empty and not found in cache.",
|
|
1381
|
-
},
|
|
1382
|
-
logoutRequestEmptyError: {
|
|
1383
|
-
code: "logout_request_empty",
|
|
1384
|
-
desc: "The logout request was null or undefined.",
|
|
1385
|
-
},
|
|
1386
|
-
invalidCodeChallengeMethod: {
|
|
1387
|
-
code: "invalid_code_challenge_method",
|
|
1388
|
-
desc: 'code_challenge_method passed is invalid. Valid values are "plain" and "S256".',
|
|
1389
|
-
},
|
|
1390
|
-
invalidCodeChallengeParams: {
|
|
1391
|
-
code: "pkce_params_missing",
|
|
1392
|
-
desc: "Both params: code_challenge and code_challenge_method are to be passed if to be sent in the request",
|
|
1393
|
-
},
|
|
1394
|
-
invalidCloudDiscoveryMetadata: {
|
|
1395
|
-
code: "invalid_cloud_discovery_metadata",
|
|
1396
|
-
desc: "Invalid cloudDiscoveryMetadata provided. Must be a stringified JSON object containing tenant_discovery_endpoint and metadata fields",
|
|
1397
|
-
},
|
|
1398
|
-
invalidAuthorityMetadata: {
|
|
1399
|
-
code: "invalid_authority_metadata",
|
|
1400
|
-
desc: "Invalid authorityMetadata provided. Must by a stringified JSON object containing authorization_endpoint, token_endpoint, issuer fields.",
|
|
1401
|
-
},
|
|
1402
|
-
untrustedAuthority: {
|
|
1403
|
-
code: "untrusted_authority",
|
|
1404
|
-
desc: "The provided authority is not a trusted authority. Please include this authority in the knownAuthorities config parameter.",
|
|
1405
|
-
},
|
|
1406
|
-
invalidAzureCloudInstance: {
|
|
1407
|
-
code: "invalid_azure_cloud_instance",
|
|
1408
|
-
desc: "Invalid AzureCloudInstance provided. Please refer MSAL JS docs: aks.ms/msaljs/azure_cloud_instance for valid values",
|
|
1409
|
-
},
|
|
1410
|
-
missingSshJwk: {
|
|
1411
|
-
code: "missing_ssh_jwk",
|
|
1412
|
-
desc: "Missing sshJwk in SSH certificate request. A stringified JSON Web Key is required when using the SSH authentication scheme.",
|
|
1413
|
-
},
|
|
1414
|
-
missingSshKid: {
|
|
1415
|
-
code: "missing_ssh_kid",
|
|
1416
|
-
desc: "Missing sshKid in SSH certificate request. A string that uniquely identifies the public SSH key is required when using the SSH authentication scheme.",
|
|
1417
|
-
},
|
|
1418
|
-
missingNonceAuthenticationHeader: {
|
|
1419
|
-
code: "missing_nonce_authentication_header",
|
|
1420
|
-
desc: "Unable to find an authentication header containing server nonce. Either the Authentication-Info or WWW-Authenticate headers must be present in order to obtain a server nonce.",
|
|
1421
|
-
},
|
|
1422
|
-
invalidAuthenticationHeader: {
|
|
1423
|
-
code: "invalid_authentication_header",
|
|
1424
|
-
desc: "Invalid authentication header provided",
|
|
1425
|
-
},
|
|
1426
|
-
cannotSetOIDCOptions: {
|
|
1427
|
-
code: "cannot_set_OIDCOptions",
|
|
1428
|
-
desc: "Cannot set OIDCOptions parameter. Please change the protocol mode to OIDC or use a non-Microsoft authority.",
|
|
1429
|
-
},
|
|
1430
|
-
cannotAllowNativeBroker: {
|
|
1431
|
-
code: "cannot_allow_native_broker",
|
|
1432
|
-
desc: "Cannot set allowNativeBroker parameter to true when not in AAD protocol mode.",
|
|
1433
|
-
},
|
|
1434
|
-
authorityMismatch: {
|
|
1435
|
-
code: "authority_mismatch",
|
|
1436
|
-
desc: "Authority mismatch error. Authority provided in login request or PublicClientApplication config does not match the environment of the provided account. Please use a matching account or make an interactive request to login to this authority.",
|
|
1437
|
-
},
|
|
1438
|
-
};
|
|
1439
|
-
/**
|
|
1440
|
-
* Error thrown when there is an error in configuration of the MSAL.js library.
|
|
1582
|
+
* The ScopeSet class creates a set of scopes. Scopes are case-insensitive, unique values, so the Set object in JS makes
|
|
1583
|
+
* the most sense to implement for this class. All scopes are trimmed and converted to lower case strings in intersection and union functions
|
|
1584
|
+
* to ensure uniqueness of strings.
|
|
1441
1585
|
*/
|
|
1442
|
-
class
|
|
1443
|
-
constructor(
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1586
|
+
class ScopeSet {
|
|
1587
|
+
constructor(inputScopes) {
|
|
1588
|
+
// Filter empty string and null/undefined array items
|
|
1589
|
+
const scopeArr = inputScopes
|
|
1590
|
+
? StringUtils.trimArrayEntries([...inputScopes])
|
|
1591
|
+
: [];
|
|
1592
|
+
const filteredInput = scopeArr
|
|
1593
|
+
? StringUtils.removeEmptyStringsFromArray(scopeArr)
|
|
1594
|
+
: [];
|
|
1595
|
+
// Validate and filter scopes (validate function throws if validation fails)
|
|
1596
|
+
this.validateInputScopes(filteredInput);
|
|
1597
|
+
this.scopes = new Set(); // Iterator in constructor not supported by IE11
|
|
1598
|
+
filteredInput.forEach((scope) => this.scopes.add(scope));
|
|
1453
1599
|
}
|
|
1454
1600
|
/**
|
|
1455
|
-
*
|
|
1601
|
+
* Factory method to create ScopeSet from space-delimited string
|
|
1602
|
+
* @param inputScopeString
|
|
1603
|
+
* @param appClientId
|
|
1604
|
+
* @param scopesRequired
|
|
1456
1605
|
*/
|
|
1457
|
-
static
|
|
1458
|
-
|
|
1606
|
+
static fromString(inputScopeString) {
|
|
1607
|
+
const scopeString = inputScopeString || Constants.EMPTY_STRING;
|
|
1608
|
+
const inputScopes = scopeString.split(" ");
|
|
1609
|
+
return new ScopeSet(inputScopes);
|
|
1459
1610
|
}
|
|
1460
1611
|
/**
|
|
1461
|
-
* Creates
|
|
1612
|
+
* Creates the set of scopes to search for in cache lookups
|
|
1613
|
+
* @param inputScopeString
|
|
1614
|
+
* @returns
|
|
1462
1615
|
*/
|
|
1463
|
-
static
|
|
1464
|
-
|
|
1616
|
+
static createSearchScopes(inputScopeString) {
|
|
1617
|
+
const scopeSet = new ScopeSet(inputScopeString);
|
|
1618
|
+
if (!scopeSet.containsOnlyOIDCScopes()) {
|
|
1619
|
+
scopeSet.removeOIDCScopes();
|
|
1620
|
+
}
|
|
1621
|
+
else {
|
|
1622
|
+
scopeSet.removeScope(Constants.OFFLINE_ACCESS_SCOPE);
|
|
1623
|
+
}
|
|
1624
|
+
return scopeSet;
|
|
1465
1625
|
}
|
|
1466
1626
|
/**
|
|
1467
|
-
*
|
|
1468
|
-
* @param
|
|
1627
|
+
* Used to validate the scopes input parameter requested by the developer.
|
|
1628
|
+
* @param {Array<string>} inputScopes - Developer requested permissions. Not all scopes are guaranteed to be included in the access token returned.
|
|
1629
|
+
* @param {boolean} scopesRequired - Boolean indicating whether the scopes array is required or not
|
|
1469
1630
|
*/
|
|
1470
|
-
|
|
1471
|
-
|
|
1631
|
+
validateInputScopes(inputScopes) {
|
|
1632
|
+
// Check if scopes are required but not given or is an empty array
|
|
1633
|
+
if (!inputScopes || inputScopes.length < 1) {
|
|
1634
|
+
throw ClientConfigurationError.createEmptyScopesArrayError();
|
|
1635
|
+
}
|
|
1472
1636
|
}
|
|
1473
1637
|
/**
|
|
1474
|
-
*
|
|
1475
|
-
* @param
|
|
1638
|
+
* Check if a given scope is present in this set of scopes.
|
|
1639
|
+
* @param scope
|
|
1476
1640
|
*/
|
|
1477
|
-
|
|
1478
|
-
|
|
1641
|
+
containsScope(scope) {
|
|
1642
|
+
const lowerCaseScopes = this.printScopesLowerCase().split(" ");
|
|
1643
|
+
const lowerCaseScopesSet = new ScopeSet(lowerCaseScopes);
|
|
1644
|
+
// compare lowercase scopes
|
|
1645
|
+
return scope
|
|
1646
|
+
? lowerCaseScopesSet.scopes.has(scope.toLowerCase())
|
|
1647
|
+
: false;
|
|
1479
1648
|
}
|
|
1480
1649
|
/**
|
|
1481
|
-
*
|
|
1482
|
-
* @param
|
|
1650
|
+
* Check if a set of scopes is present in this set of scopes.
|
|
1651
|
+
* @param scopeSet
|
|
1483
1652
|
*/
|
|
1484
|
-
|
|
1485
|
-
|
|
1653
|
+
containsScopeSet(scopeSet) {
|
|
1654
|
+
if (!scopeSet || scopeSet.scopes.size <= 0) {
|
|
1655
|
+
return false;
|
|
1656
|
+
}
|
|
1657
|
+
return (this.scopes.size >= scopeSet.scopes.size &&
|
|
1658
|
+
scopeSet.asArray().every((scope) => this.containsScope(scope)));
|
|
1486
1659
|
}
|
|
1487
1660
|
/**
|
|
1488
|
-
*
|
|
1489
|
-
* @param scopesValue
|
|
1661
|
+
* Check if set of scopes contains only the defaults
|
|
1490
1662
|
*/
|
|
1491
|
-
|
|
1492
|
-
|
|
1663
|
+
containsOnlyOIDCScopes() {
|
|
1664
|
+
let defaultScopeCount = 0;
|
|
1665
|
+
OIDC_SCOPES.forEach((defaultScope) => {
|
|
1666
|
+
if (this.containsScope(defaultScope)) {
|
|
1667
|
+
defaultScopeCount += 1;
|
|
1668
|
+
}
|
|
1669
|
+
});
|
|
1670
|
+
return this.scopes.size === defaultScopeCount;
|
|
1493
1671
|
}
|
|
1494
1672
|
/**
|
|
1495
|
-
*
|
|
1496
|
-
* @param
|
|
1673
|
+
* Appends single scope if passed
|
|
1674
|
+
* @param newScope
|
|
1497
1675
|
*/
|
|
1498
|
-
|
|
1499
|
-
|
|
1676
|
+
appendScope(newScope) {
|
|
1677
|
+
if (newScope) {
|
|
1678
|
+
this.scopes.add(newScope.trim());
|
|
1679
|
+
}
|
|
1500
1680
|
}
|
|
1501
1681
|
/**
|
|
1502
|
-
*
|
|
1503
|
-
* @param
|
|
1682
|
+
* Appends multiple scopes if passed
|
|
1683
|
+
* @param newScopes
|
|
1504
1684
|
*/
|
|
1505
|
-
|
|
1506
|
-
|
|
1685
|
+
appendScopes(newScopes) {
|
|
1686
|
+
try {
|
|
1687
|
+
newScopes.forEach((newScope) => this.appendScope(newScope));
|
|
1688
|
+
}
|
|
1689
|
+
catch (e) {
|
|
1690
|
+
throw ClientAuthError.createAppendScopeSetError(e);
|
|
1691
|
+
}
|
|
1507
1692
|
}
|
|
1508
1693
|
/**
|
|
1509
|
-
*
|
|
1694
|
+
* Removes element from set of scopes.
|
|
1695
|
+
* @param scope
|
|
1510
1696
|
*/
|
|
1511
|
-
|
|
1512
|
-
|
|
1697
|
+
removeScope(scope) {
|
|
1698
|
+
if (!scope) {
|
|
1699
|
+
throw ClientAuthError.createRemoveEmptyScopeFromSetError(scope);
|
|
1700
|
+
}
|
|
1701
|
+
this.scopes.delete(scope.trim());
|
|
1513
1702
|
}
|
|
1514
1703
|
/**
|
|
1515
|
-
*
|
|
1704
|
+
* Removes default scopes from set of scopes
|
|
1705
|
+
* Primarily used to prevent cache misses if the default scopes are not returned from the server
|
|
1516
1706
|
*/
|
|
1517
|
-
|
|
1518
|
-
|
|
1707
|
+
removeOIDCScopes() {
|
|
1708
|
+
OIDC_SCOPES.forEach((defaultScope) => {
|
|
1709
|
+
this.scopes.delete(defaultScope);
|
|
1710
|
+
});
|
|
1519
1711
|
}
|
|
1520
1712
|
/**
|
|
1521
|
-
*
|
|
1522
|
-
|
|
1523
|
-
static createEmptyTokenRequestError() {
|
|
1524
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.tokenRequestEmptyError.code, ClientConfigurationErrorMessage.tokenRequestEmptyError.desc);
|
|
1525
|
-
}
|
|
1526
|
-
/**
|
|
1527
|
-
* Throws error when an invalid code_challenge_method is passed by the user
|
|
1528
|
-
*/
|
|
1529
|
-
static createInvalidCodeChallengeMethodError() {
|
|
1530
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCodeChallengeMethod.code, ClientConfigurationErrorMessage.invalidCodeChallengeMethod.desc);
|
|
1531
|
-
}
|
|
1532
|
-
/**
|
|
1533
|
-
* Throws error when both params: code_challenge and code_challenge_method are not passed together
|
|
1534
|
-
*/
|
|
1535
|
-
static createInvalidCodeChallengeParamsError() {
|
|
1536
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCodeChallengeParams.code, ClientConfigurationErrorMessage.invalidCodeChallengeParams.desc);
|
|
1537
|
-
}
|
|
1538
|
-
/**
|
|
1539
|
-
* Throws an error when the user passes invalid cloudDiscoveryMetadata
|
|
1540
|
-
*/
|
|
1541
|
-
static createInvalidCloudDiscoveryMetadataError() {
|
|
1542
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidCloudDiscoveryMetadata.code, ClientConfigurationErrorMessage.invalidCloudDiscoveryMetadata.desc);
|
|
1543
|
-
}
|
|
1544
|
-
/**
|
|
1545
|
-
* Throws an error when the user passes invalid cloudDiscoveryMetadata
|
|
1546
|
-
*/
|
|
1547
|
-
static createInvalidAuthorityMetadataError() {
|
|
1548
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidAuthorityMetadata.code, ClientConfigurationErrorMessage.invalidAuthorityMetadata.desc);
|
|
1549
|
-
}
|
|
1550
|
-
/**
|
|
1551
|
-
* Throws error when provided authority is not a member of the trusted host list
|
|
1552
|
-
*/
|
|
1553
|
-
static createUntrustedAuthorityError() {
|
|
1554
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.untrustedAuthority.code, ClientConfigurationErrorMessage.untrustedAuthority.desc);
|
|
1555
|
-
}
|
|
1556
|
-
/**
|
|
1557
|
-
* Throws error when the AzureCloudInstance is set to an invalid value
|
|
1558
|
-
*/
|
|
1559
|
-
static createInvalidAzureCloudInstanceError() {
|
|
1560
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidAzureCloudInstance.code, ClientConfigurationErrorMessage.invalidAzureCloudInstance.desc);
|
|
1561
|
-
}
|
|
1562
|
-
/**
|
|
1563
|
-
* Throws an error when the authentication scheme is set to SSH but the SSH public key is omitted from the request
|
|
1564
|
-
*/
|
|
1565
|
-
static createMissingSshJwkError() {
|
|
1566
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.missingSshJwk.code, ClientConfigurationErrorMessage.missingSshJwk.desc);
|
|
1567
|
-
}
|
|
1568
|
-
/**
|
|
1569
|
-
* Throws an error when the authentication scheme is set to SSH but the SSH public key ID is omitted from the request
|
|
1570
|
-
*/
|
|
1571
|
-
static createMissingSshKidError() {
|
|
1572
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.missingSshKid.code, ClientConfigurationErrorMessage.missingSshKid.desc);
|
|
1573
|
-
}
|
|
1574
|
-
/**
|
|
1575
|
-
* Throws error when provided headers don't contain a header that a server nonce can be extracted from
|
|
1576
|
-
*/
|
|
1577
|
-
static createMissingNonceAuthenticationHeadersError() {
|
|
1578
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.missingNonceAuthenticationHeader.code, ClientConfigurationErrorMessage.missingNonceAuthenticationHeader.desc);
|
|
1579
|
-
}
|
|
1580
|
-
/**
|
|
1581
|
-
* Throws error when a provided header is invalid in any way
|
|
1582
|
-
*/
|
|
1583
|
-
static createInvalidAuthenticationHeaderError(invalidHeaderName, details) {
|
|
1584
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidAuthenticationHeader.code, `${ClientConfigurationErrorMessage.invalidAuthenticationHeader.desc}. Invalid header: ${invalidHeaderName}. Details: ${details}`);
|
|
1585
|
-
}
|
|
1586
|
-
/**
|
|
1587
|
-
* Throws error when provided non-default OIDCOptions when not in OIDC protocol mode
|
|
1588
|
-
*/
|
|
1589
|
-
static createCannotSetOIDCOptionsError() {
|
|
1590
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.cannotSetOIDCOptions.code, ClientConfigurationErrorMessage.cannotSetOIDCOptions.desc);
|
|
1591
|
-
}
|
|
1592
|
-
/**
|
|
1593
|
-
* Throws error when allowNativeBroker is set to true when not in AAD protocol mode
|
|
1594
|
-
*/
|
|
1595
|
-
static createCannotAllowNativeBrokerError() {
|
|
1596
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.cannotAllowNativeBroker.code, ClientConfigurationErrorMessage.cannotAllowNativeBroker.desc);
|
|
1597
|
-
}
|
|
1598
|
-
/**
|
|
1599
|
-
* Create an error when the authority provided in request does not match authority provided in account or MSAL.js configuration.
|
|
1600
|
-
*/
|
|
1601
|
-
static createAuthorityMismatchError() {
|
|
1602
|
-
return new ClientConfigurationError(ClientConfigurationErrorMessage.authorityMismatch.code, ClientConfigurationErrorMessage.authorityMismatch.desc);
|
|
1603
|
-
}
|
|
1604
|
-
}
|
|
1605
|
-
|
|
1606
|
-
/*
|
|
1607
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
1608
|
-
* Licensed under the MIT License.
|
|
1609
|
-
*/
|
|
1610
|
-
/**
|
|
1611
|
-
* The ScopeSet class creates a set of scopes. Scopes are case-insensitive, unique values, so the Set object in JS makes
|
|
1612
|
-
* the most sense to implement for this class. All scopes are trimmed and converted to lower case strings in intersection and union functions
|
|
1613
|
-
* to ensure uniqueness of strings.
|
|
1614
|
-
*/
|
|
1615
|
-
class ScopeSet {
|
|
1616
|
-
constructor(inputScopes) {
|
|
1617
|
-
// Filter empty string and null/undefined array items
|
|
1618
|
-
const scopeArr = inputScopes
|
|
1619
|
-
? StringUtils.trimArrayEntries([...inputScopes])
|
|
1620
|
-
: [];
|
|
1621
|
-
const filteredInput = scopeArr
|
|
1622
|
-
? StringUtils.removeEmptyStringsFromArray(scopeArr)
|
|
1623
|
-
: [];
|
|
1624
|
-
// Validate and filter scopes (validate function throws if validation fails)
|
|
1625
|
-
this.validateInputScopes(filteredInput);
|
|
1626
|
-
this.scopes = new Set(); // Iterator in constructor not supported by IE11
|
|
1627
|
-
filteredInput.forEach((scope) => this.scopes.add(scope));
|
|
1628
|
-
}
|
|
1629
|
-
/**
|
|
1630
|
-
* Factory method to create ScopeSet from space-delimited string
|
|
1631
|
-
* @param inputScopeString
|
|
1632
|
-
* @param appClientId
|
|
1633
|
-
* @param scopesRequired
|
|
1634
|
-
*/
|
|
1635
|
-
static fromString(inputScopeString) {
|
|
1636
|
-
const scopeString = inputScopeString || Constants.EMPTY_STRING;
|
|
1637
|
-
const inputScopes = scopeString.split(" ");
|
|
1638
|
-
return new ScopeSet(inputScopes);
|
|
1639
|
-
}
|
|
1640
|
-
/**
|
|
1641
|
-
* Creates the set of scopes to search for in cache lookups
|
|
1642
|
-
* @param inputScopeString
|
|
1643
|
-
* @returns
|
|
1644
|
-
*/
|
|
1645
|
-
static createSearchScopes(inputScopeString) {
|
|
1646
|
-
const scopeSet = new ScopeSet(inputScopeString);
|
|
1647
|
-
if (!scopeSet.containsOnlyOIDCScopes()) {
|
|
1648
|
-
scopeSet.removeOIDCScopes();
|
|
1649
|
-
}
|
|
1650
|
-
else {
|
|
1651
|
-
scopeSet.removeScope(Constants.OFFLINE_ACCESS_SCOPE);
|
|
1652
|
-
}
|
|
1653
|
-
return scopeSet;
|
|
1654
|
-
}
|
|
1655
|
-
/**
|
|
1656
|
-
* Used to validate the scopes input parameter requested by the developer.
|
|
1657
|
-
* @param {Array<string>} inputScopes - Developer requested permissions. Not all scopes are guaranteed to be included in the access token returned.
|
|
1658
|
-
* @param {boolean} scopesRequired - Boolean indicating whether the scopes array is required or not
|
|
1659
|
-
*/
|
|
1660
|
-
validateInputScopes(inputScopes) {
|
|
1661
|
-
// Check if scopes are required but not given or is an empty array
|
|
1662
|
-
if (!inputScopes || inputScopes.length < 1) {
|
|
1663
|
-
throw ClientConfigurationError.createEmptyScopesArrayError();
|
|
1664
|
-
}
|
|
1665
|
-
}
|
|
1666
|
-
/**
|
|
1667
|
-
* Check if a given scope is present in this set of scopes.
|
|
1668
|
-
* @param scope
|
|
1669
|
-
*/
|
|
1670
|
-
containsScope(scope) {
|
|
1671
|
-
const lowerCaseScopes = this.printScopesLowerCase().split(" ");
|
|
1672
|
-
const lowerCaseScopesSet = new ScopeSet(lowerCaseScopes);
|
|
1673
|
-
// compare lowercase scopes
|
|
1674
|
-
return !StringUtils.isEmpty(scope)
|
|
1675
|
-
? lowerCaseScopesSet.scopes.has(scope.toLowerCase())
|
|
1676
|
-
: false;
|
|
1677
|
-
}
|
|
1678
|
-
/**
|
|
1679
|
-
* Check if a set of scopes is present in this set of scopes.
|
|
1680
|
-
* @param scopeSet
|
|
1681
|
-
*/
|
|
1682
|
-
containsScopeSet(scopeSet) {
|
|
1683
|
-
if (!scopeSet || scopeSet.scopes.size <= 0) {
|
|
1684
|
-
return false;
|
|
1685
|
-
}
|
|
1686
|
-
return (this.scopes.size >= scopeSet.scopes.size &&
|
|
1687
|
-
scopeSet.asArray().every((scope) => this.containsScope(scope)));
|
|
1688
|
-
}
|
|
1689
|
-
/**
|
|
1690
|
-
* Check if set of scopes contains only the defaults
|
|
1691
|
-
*/
|
|
1692
|
-
containsOnlyOIDCScopes() {
|
|
1693
|
-
let defaultScopeCount = 0;
|
|
1694
|
-
OIDC_SCOPES.forEach((defaultScope) => {
|
|
1695
|
-
if (this.containsScope(defaultScope)) {
|
|
1696
|
-
defaultScopeCount += 1;
|
|
1697
|
-
}
|
|
1698
|
-
});
|
|
1699
|
-
return this.scopes.size === defaultScopeCount;
|
|
1700
|
-
}
|
|
1701
|
-
/**
|
|
1702
|
-
* Appends single scope if passed
|
|
1703
|
-
* @param newScope
|
|
1704
|
-
*/
|
|
1705
|
-
appendScope(newScope) {
|
|
1706
|
-
if (!StringUtils.isEmpty(newScope)) {
|
|
1707
|
-
this.scopes.add(newScope.trim());
|
|
1708
|
-
}
|
|
1709
|
-
}
|
|
1710
|
-
/**
|
|
1711
|
-
* Appends multiple scopes if passed
|
|
1712
|
-
* @param newScopes
|
|
1713
|
-
*/
|
|
1714
|
-
appendScopes(newScopes) {
|
|
1715
|
-
try {
|
|
1716
|
-
newScopes.forEach((newScope) => this.appendScope(newScope));
|
|
1717
|
-
}
|
|
1718
|
-
catch (e) {
|
|
1719
|
-
throw ClientAuthError.createAppendScopeSetError(e);
|
|
1720
|
-
}
|
|
1721
|
-
}
|
|
1722
|
-
/**
|
|
1723
|
-
* Removes element from set of scopes.
|
|
1724
|
-
* @param scope
|
|
1725
|
-
*/
|
|
1726
|
-
removeScope(scope) {
|
|
1727
|
-
if (StringUtils.isEmpty(scope)) {
|
|
1728
|
-
throw ClientAuthError.createRemoveEmptyScopeFromSetError(scope);
|
|
1729
|
-
}
|
|
1730
|
-
this.scopes.delete(scope.trim());
|
|
1731
|
-
}
|
|
1732
|
-
/**
|
|
1733
|
-
* Removes default scopes from set of scopes
|
|
1734
|
-
* Primarily used to prevent cache misses if the default scopes are not returned from the server
|
|
1735
|
-
*/
|
|
1736
|
-
removeOIDCScopes() {
|
|
1737
|
-
OIDC_SCOPES.forEach((defaultScope) => {
|
|
1738
|
-
this.scopes.delete(defaultScope);
|
|
1739
|
-
});
|
|
1740
|
-
}
|
|
1741
|
-
/**
|
|
1742
|
-
* Combines an array of scopes with the current set of scopes.
|
|
1743
|
-
* @param otherScopes
|
|
1713
|
+
* Combines an array of scopes with the current set of scopes.
|
|
1714
|
+
* @param otherScopes
|
|
1744
1715
|
*/
|
|
1745
1716
|
unionScopeSets(otherScopes) {
|
|
1746
1717
|
if (!otherScopes) {
|
|
@@ -1811,7 +1782,7 @@ class ScopeSet {
|
|
|
1811
1782
|
* @param crypto
|
|
1812
1783
|
*/
|
|
1813
1784
|
function buildClientInfo(rawClientInfo, crypto) {
|
|
1814
|
-
if (
|
|
1785
|
+
if (!rawClientInfo) {
|
|
1815
1786
|
throw ClientAuthError.createClientInfoEmptyError();
|
|
1816
1787
|
}
|
|
1817
1788
|
try {
|
|
@@ -1827,7 +1798,7 @@ function buildClientInfo(rawClientInfo, crypto) {
|
|
|
1827
1798
|
* @param homeAccountId
|
|
1828
1799
|
*/
|
|
1829
1800
|
function buildClientInfoFromHomeAccountId(homeAccountId) {
|
|
1830
|
-
if (
|
|
1801
|
+
if (!homeAccountId) {
|
|
1831
1802
|
throw ClientAuthError.createClientInfoDecodingError("Home account ID was empty.");
|
|
1832
1803
|
}
|
|
1833
1804
|
const clientInfoParts = homeAccountId.split(Separators.CLIENT_INFO_SEPARATOR, 2);
|
|
@@ -2030,8 +2001,7 @@ class AccountEntity {
|
|
|
2030
2001
|
if (serverClientInfo) {
|
|
2031
2002
|
try {
|
|
2032
2003
|
const clientInfo = buildClientInfo(serverClientInfo, cryptoObj);
|
|
2033
|
-
if (
|
|
2034
|
-
!StringUtils.isEmpty(clientInfo.utid)) {
|
|
2004
|
+
if (clientInfo.uid && clientInfo.utid) {
|
|
2035
2005
|
return `${clientInfo.uid}${Separators.CLIENT_INFO_SEPARATOR}${clientInfo.utid}`;
|
|
2036
2006
|
}
|
|
2037
2007
|
}
|
|
@@ -2092,50 +2062,67 @@ class AccountEntity {
|
|
|
2092
2062
|
* Licensed under the MIT License.
|
|
2093
2063
|
*/
|
|
2094
2064
|
/**
|
|
2095
|
-
*
|
|
2065
|
+
* Extract token by decoding the rawToken
|
|
2066
|
+
*
|
|
2067
|
+
* @param encodedToken
|
|
2096
2068
|
*/
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2069
|
+
function extractTokenClaims(encodedToken, base64Decode) {
|
|
2070
|
+
const jswPayload = getJWSPayload(encodedToken);
|
|
2071
|
+
// token will be decoded to get the username
|
|
2072
|
+
try {
|
|
2073
|
+
// base64Decode() should throw an error if there is an issue
|
|
2074
|
+
const base64Decoded = base64Decode(jswPayload);
|
|
2075
|
+
return JSON.parse(base64Decoded);
|
|
2104
2076
|
}
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
}
|
|
2077
|
+
catch (err) {
|
|
2078
|
+
throw ClientAuthError.createTokenParsingError(err);
|
|
2079
|
+
}
|
|
2080
|
+
}
|
|
2081
|
+
/**
|
|
2082
|
+
* decode a JWT
|
|
2083
|
+
*
|
|
2084
|
+
* @param authToken
|
|
2085
|
+
*/
|
|
2086
|
+
function getJWSPayload(authToken) {
|
|
2087
|
+
if (!authToken) {
|
|
2088
|
+
throw ClientAuthError.createTokenNullOrEmptyError(authToken);
|
|
2089
|
+
}
|
|
2090
|
+
const tokenPartsRegex = /^([^\.\s]*)\.([^\.\s]+)\.([^\.\s]*)$/;
|
|
2091
|
+
const matches = tokenPartsRegex.exec(authToken);
|
|
2092
|
+
if (!matches || matches.length < 4) {
|
|
2093
|
+
throw ClientAuthError.createTokenParsingError(`Given token is malformed: ${JSON.stringify(authToken)}`);
|
|
2122
2094
|
}
|
|
2123
2095
|
/**
|
|
2124
|
-
*
|
|
2096
|
+
* const crackedToken = {
|
|
2097
|
+
* header: matches[1],
|
|
2098
|
+
* JWSPayload: matches[2],
|
|
2099
|
+
* JWSSig: matches[3],
|
|
2100
|
+
* };
|
|
2125
2101
|
*/
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2102
|
+
return matches[2];
|
|
2103
|
+
}
|
|
2104
|
+
/**
|
|
2105
|
+
* Determine if the token's max_age has transpired
|
|
2106
|
+
*/
|
|
2107
|
+
function checkMaxAge(authTime, maxAge) {
|
|
2108
|
+
/*
|
|
2109
|
+
* per https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
|
|
2110
|
+
* To force an immediate re-authentication: If an app requires that a user re-authenticate prior to access,
|
|
2111
|
+
* provide a value of 0 for the max_age parameter and the AS will force a fresh login.
|
|
2112
|
+
*/
|
|
2113
|
+
const fiveMinuteSkew = 300000; // five minutes in milliseconds
|
|
2114
|
+
if (maxAge === 0 || Date.now() - fiveMinuteSkew > authTime + maxAge) {
|
|
2115
|
+
throw ClientAuthError.createMaxAgeTranspiredError();
|
|
2136
2116
|
}
|
|
2137
2117
|
}
|
|
2138
2118
|
|
|
2119
|
+
var AuthToken = /*#__PURE__*/Object.freeze({
|
|
2120
|
+
__proto__: null,
|
|
2121
|
+
checkMaxAge: checkMaxAge,
|
|
2122
|
+
extractTokenClaims: extractTokenClaims,
|
|
2123
|
+
getJWSPayload: getJWSPayload
|
|
2124
|
+
});
|
|
2125
|
+
|
|
2139
2126
|
/*
|
|
2140
2127
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2141
2128
|
* Licensed under the MIT License.
|
|
@@ -2193,7 +2180,7 @@ class CacheManager {
|
|
|
2193
2180
|
const idToken = this.getIdToken(accountInfo);
|
|
2194
2181
|
if (idToken) {
|
|
2195
2182
|
accountInfo.idToken = idToken.secret;
|
|
2196
|
-
accountInfo.idTokenClaims =
|
|
2183
|
+
accountInfo.idTokenClaims = extractTokenClaims(idToken.secret, this.cryptoImpl.base64Decode);
|
|
2197
2184
|
}
|
|
2198
2185
|
return accountInfo;
|
|
2199
2186
|
}
|
|
@@ -2589,7 +2576,7 @@ class CacheManager {
|
|
|
2589
2576
|
const cachedRefreshToken = this.getRefreshToken(account, false, tokenKeys);
|
|
2590
2577
|
const cachedAppMetadata = this.readAppMetadataFromCache(environment);
|
|
2591
2578
|
if (cachedAccount && cachedIdToken) {
|
|
2592
|
-
cachedAccount.idTokenClaims =
|
|
2579
|
+
cachedAccount.idTokenClaims = extractTokenClaims(cachedIdToken.secret, this.cryptoImpl.base64Decode);
|
|
2593
2580
|
}
|
|
2594
2581
|
return {
|
|
2595
2582
|
account: cachedAccount,
|
|
@@ -2745,7 +2732,7 @@ class CacheManager {
|
|
|
2745
2732
|
else if (numAccessTokens > 1) {
|
|
2746
2733
|
this.commonLogger.info("CacheManager:getAccessToken - Multiple access tokens found, clearing them");
|
|
2747
2734
|
accessTokens.forEach((accessToken) => {
|
|
2748
|
-
this.removeAccessToken(accessToken.generateCredentialKey());
|
|
2735
|
+
void this.removeAccessToken(accessToken.generateCredentialKey());
|
|
2749
2736
|
});
|
|
2750
2737
|
return null;
|
|
2751
2738
|
}
|
|
@@ -3427,7 +3414,7 @@ class RequestValidator {
|
|
|
3427
3414
|
* @param redirectUri
|
|
3428
3415
|
*/
|
|
3429
3416
|
static validateRedirectUri(redirectUri) {
|
|
3430
|
-
if (
|
|
3417
|
+
if (!redirectUri) {
|
|
3431
3418
|
throw ClientConfigurationError.createRedirectUriEmptyError();
|
|
3432
3419
|
}
|
|
3433
3420
|
}
|
|
@@ -3458,8 +3445,7 @@ class RequestValidator {
|
|
|
3458
3445
|
* @param codeChallengeMethod
|
|
3459
3446
|
*/
|
|
3460
3447
|
static validateCodeChallengeParams(codeChallenge, codeChallengeMethod) {
|
|
3461
|
-
if (
|
|
3462
|
-
StringUtils.isEmpty(codeChallengeMethod)) {
|
|
3448
|
+
if (!codeChallenge || !codeChallengeMethod) {
|
|
3463
3449
|
throw ClientConfigurationError.createInvalidCodeChallengeParamsError();
|
|
3464
3450
|
}
|
|
3465
3451
|
else {
|
|
@@ -3487,7 +3473,7 @@ class RequestValidator {
|
|
|
3487
3473
|
return {};
|
|
3488
3474
|
}
|
|
3489
3475
|
// Remove any query parameters already included in SSO params
|
|
3490
|
-
queryParams.forEach((
|
|
3476
|
+
queryParams.forEach((_value, key) => {
|
|
3491
3477
|
if (eQParams[key]) {
|
|
3492
3478
|
delete eQParams[key];
|
|
3493
3479
|
}
|
|
@@ -3670,7 +3656,7 @@ class RequestParameterBuilder {
|
|
|
3670
3656
|
* @param state
|
|
3671
3657
|
*/
|
|
3672
3658
|
addState(state) {
|
|
3673
|
-
if (
|
|
3659
|
+
if (state) {
|
|
3674
3660
|
this.parameters.set(AADServerParamKeys.STATE, encodeURIComponent(state));
|
|
3675
3661
|
}
|
|
3676
3662
|
}
|
|
@@ -3737,7 +3723,7 @@ class RequestParameterBuilder {
|
|
|
3737
3723
|
* @param clientAssertion
|
|
3738
3724
|
*/
|
|
3739
3725
|
addClientAssertion(clientAssertion) {
|
|
3740
|
-
if (
|
|
3726
|
+
if (clientAssertion) {
|
|
3741
3727
|
this.parameters.set(AADServerParamKeys.CLIENT_ASSERTION, encodeURIComponent(clientAssertion));
|
|
3742
3728
|
}
|
|
3743
3729
|
}
|
|
@@ -3746,7 +3732,7 @@ class RequestParameterBuilder {
|
|
|
3746
3732
|
* @param clientAssertionType
|
|
3747
3733
|
*/
|
|
3748
3734
|
addClientAssertionType(clientAssertionType) {
|
|
3749
|
-
if (
|
|
3735
|
+
if (clientAssertionType) {
|
|
3750
3736
|
this.parameters.set(AADServerParamKeys.CLIENT_ASSERTION_TYPE, encodeURIComponent(clientAssertionType));
|
|
3751
3737
|
}
|
|
3752
3738
|
}
|
|
@@ -3833,7 +3819,7 @@ class RequestParameterBuilder {
|
|
|
3833
3819
|
* @param cnfString
|
|
3834
3820
|
*/
|
|
3835
3821
|
addPopToken(cnfString) {
|
|
3836
|
-
if (
|
|
3822
|
+
if (cnfString) {
|
|
3837
3823
|
this.parameters.set(AADServerParamKeys.TOKEN_TYPE, AuthenticationScheme.POP);
|
|
3838
3824
|
this.parameters.set(AADServerParamKeys.REQ_CNF, encodeURIComponent(cnfString));
|
|
3839
3825
|
}
|
|
@@ -3842,7 +3828,7 @@ class RequestParameterBuilder {
|
|
|
3842
3828
|
* add SSH JWK and key ID to query params
|
|
3843
3829
|
*/
|
|
3844
3830
|
addSshJwk(sshJwkString) {
|
|
3845
|
-
if (
|
|
3831
|
+
if (sshJwkString) {
|
|
3846
3832
|
this.parameters.set(AADServerParamKeys.TOKEN_TYPE, AuthenticationScheme.SSH);
|
|
3847
3833
|
this.parameters.set(AADServerParamKeys.REQ_CNF, encodeURIComponent(sshJwkString));
|
|
3848
3834
|
}
|
|
@@ -3884,18 +3870,253 @@ class RequestParameterBuilder {
|
|
|
3884
3870
|
* Licensed under the MIT License.
|
|
3885
3871
|
*/
|
|
3886
3872
|
/**
|
|
3887
|
-
*
|
|
3888
|
-
*
|
|
3873
|
+
* Enumeration of operations that are instrumented by have their performance measured by the PerformanceClient.
|
|
3874
|
+
*
|
|
3875
|
+
* @export
|
|
3876
|
+
* @enum {number}
|
|
3889
3877
|
*/
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
3893
|
-
|
|
3894
|
-
|
|
3895
|
-
|
|
3896
|
-
|
|
3897
|
-
|
|
3898
|
-
|
|
3878
|
+
const PerformanceEvents = {
|
|
3879
|
+
/**
|
|
3880
|
+
* acquireTokenByCode API (msal-browser and msal-node).
|
|
3881
|
+
* Used to acquire tokens by trading an authorization code against the token endpoint.
|
|
3882
|
+
*/
|
|
3883
|
+
AcquireTokenByCode: "acquireTokenByCode",
|
|
3884
|
+
/**
|
|
3885
|
+
* acquireTokenByRefreshToken API (msal-browser and msal-node).
|
|
3886
|
+
* Used to renew an access token using a refresh token against the token endpoint.
|
|
3887
|
+
*/
|
|
3888
|
+
AcquireTokenByRefreshToken: "acquireTokenByRefreshToken",
|
|
3889
|
+
/**
|
|
3890
|
+
* acquireTokenSilent API (msal-browser and msal-node).
|
|
3891
|
+
* Used to silently acquire a new access token (from the cache or the network).
|
|
3892
|
+
*/
|
|
3893
|
+
AcquireTokenSilent: "acquireTokenSilent",
|
|
3894
|
+
/**
|
|
3895
|
+
* acquireTokenSilentAsync (msal-browser).
|
|
3896
|
+
* Internal API for acquireTokenSilent.
|
|
3897
|
+
*/
|
|
3898
|
+
AcquireTokenSilentAsync: "acquireTokenSilentAsync",
|
|
3899
|
+
/**
|
|
3900
|
+
* acquireTokenPopup (msal-browser).
|
|
3901
|
+
* Used to acquire a new access token interactively through pop ups
|
|
3902
|
+
*/
|
|
3903
|
+
AcquireTokenPopup: "acquireTokenPopup",
|
|
3904
|
+
/**
|
|
3905
|
+
* getPublicKeyThumbprint API in CryptoOpts class (msal-browser).
|
|
3906
|
+
* Used to generate a public/private keypair and generate a public key thumbprint for pop requests.
|
|
3907
|
+
*/
|
|
3908
|
+
CryptoOptsGetPublicKeyThumbprint: "cryptoOptsGetPublicKeyThumbprint",
|
|
3909
|
+
/**
|
|
3910
|
+
* signJwt API in CryptoOpts class (msal-browser).
|
|
3911
|
+
* Used to signed a pop token.
|
|
3912
|
+
*/
|
|
3913
|
+
CryptoOptsSignJwt: "cryptoOptsSignJwt",
|
|
3914
|
+
/**
|
|
3915
|
+
* acquireToken API in the SilentCacheClient class (msal-browser).
|
|
3916
|
+
* Used to read access tokens from the cache.
|
|
3917
|
+
*/
|
|
3918
|
+
SilentCacheClientAcquireToken: "silentCacheClientAcquireToken",
|
|
3919
|
+
/**
|
|
3920
|
+
* acquireToken API in the SilentIframeClient class (msal-browser).
|
|
3921
|
+
* Used to acquire a new set of tokens from the authorize endpoint in a hidden iframe.
|
|
3922
|
+
*/
|
|
3923
|
+
SilentIframeClientAcquireToken: "silentIframeClientAcquireToken",
|
|
3924
|
+
/**
|
|
3925
|
+
* acquireToken API in SilentRereshClient (msal-browser).
|
|
3926
|
+
* Used to acquire a new set of tokens from the token endpoint using a refresh token.
|
|
3927
|
+
*/
|
|
3928
|
+
SilentRefreshClientAcquireToken: "silentRefreshClientAcquireToken",
|
|
3929
|
+
/**
|
|
3930
|
+
* ssoSilent API (msal-browser).
|
|
3931
|
+
* Used to silently acquire an authorization code and set of tokens using a hidden iframe.
|
|
3932
|
+
*/
|
|
3933
|
+
SsoSilent: "ssoSilent",
|
|
3934
|
+
/**
|
|
3935
|
+
* getDiscoveredAuthority API in StandardInteractionClient class (msal-browser).
|
|
3936
|
+
* Used to load authority metadata for a request.
|
|
3937
|
+
*/
|
|
3938
|
+
StandardInteractionClientGetDiscoveredAuthority: "standardInteractionClientGetDiscoveredAuthority",
|
|
3939
|
+
/**
|
|
3940
|
+
* acquireToken APIs in msal-browser.
|
|
3941
|
+
* Used to make an /authorize endpoint call with native brokering enabled.
|
|
3942
|
+
*/
|
|
3943
|
+
FetchAccountIdWithNativeBroker: "fetchAccountIdWithNativeBroker",
|
|
3944
|
+
/**
|
|
3945
|
+
* acquireToken API in NativeInteractionClient class (msal-browser).
|
|
3946
|
+
* Used to acquire a token from Native component when native brokering is enabled.
|
|
3947
|
+
*/
|
|
3948
|
+
NativeInteractionClientAcquireToken: "nativeInteractionClientAcquireToken",
|
|
3949
|
+
/**
|
|
3950
|
+
* Time spent creating default headers for requests to token endpoint
|
|
3951
|
+
*/
|
|
3952
|
+
BaseClientCreateTokenRequestHeaders: "baseClientCreateTokenRequestHeaders",
|
|
3953
|
+
/**
|
|
3954
|
+
* Time spent sending/waiting for the response of a request to the token endpoint
|
|
3955
|
+
*/
|
|
3956
|
+
BaseClientExecutePostToTokenEndpoint: "baseClientExecutePostToTokenEndpoint",
|
|
3957
|
+
/**
|
|
3958
|
+
* Used to measure the time taken for completing embedded-broker handshake (PW-Broker).
|
|
3959
|
+
*/
|
|
3960
|
+
BrokerHandhshake: "brokerHandshake",
|
|
3961
|
+
/**
|
|
3962
|
+
* acquireTokenByRefreshToken API in BrokerClientApplication (PW-Broker) .
|
|
3963
|
+
*/
|
|
3964
|
+
AcquireTokenByRefreshTokenInBroker: "acquireTokenByRefreshTokenInBroker",
|
|
3965
|
+
/**
|
|
3966
|
+
* Time taken for token acquisition by broker
|
|
3967
|
+
*/
|
|
3968
|
+
AcquireTokenByBroker: "acquireTokenByBroker",
|
|
3969
|
+
/**
|
|
3970
|
+
* Time spent on the network for refresh token acquisition
|
|
3971
|
+
*/
|
|
3972
|
+
RefreshTokenClientExecuteTokenRequest: "refreshTokenClientExecuteTokenRequest",
|
|
3973
|
+
/**
|
|
3974
|
+
* Time taken for acquiring refresh token , records RT size
|
|
3975
|
+
*/
|
|
3976
|
+
RefreshTokenClientAcquireToken: "refreshTokenClientAcquireToken",
|
|
3977
|
+
/**
|
|
3978
|
+
* Time taken for acquiring cached refresh token
|
|
3979
|
+
*/
|
|
3980
|
+
RefreshTokenClientAcquireTokenWithCachedRefreshToken: "refreshTokenClientAcquireTokenWithCachedRefreshToken",
|
|
3981
|
+
/**
|
|
3982
|
+
* acquireTokenByRefreshToken API in RefreshTokenClient (msal-common).
|
|
3983
|
+
*/
|
|
3984
|
+
RefreshTokenClientAcquireTokenByRefreshToken: "refreshTokenClientAcquireTokenByRefreshToken",
|
|
3985
|
+
/**
|
|
3986
|
+
* Helper function to create token request body in RefreshTokenClient (msal-common).
|
|
3987
|
+
*/
|
|
3988
|
+
RefreshTokenClientCreateTokenRequestBody: "refreshTokenClientCreateTokenRequestBody",
|
|
3989
|
+
/**
|
|
3990
|
+
* acquireTokenFromCache (msal-browser).
|
|
3991
|
+
* Internal API for acquiring token from cache
|
|
3992
|
+
*/
|
|
3993
|
+
AcquireTokenFromCache: "acquireTokenFromCache",
|
|
3994
|
+
/**
|
|
3995
|
+
* acquireTokenBySilentIframe (msal-browser).
|
|
3996
|
+
* Internal API for acquiring token by silent Iframe
|
|
3997
|
+
*/
|
|
3998
|
+
AcquireTokenBySilentIframe: "acquireTokenBySilentIframe",
|
|
3999
|
+
/**
|
|
4000
|
+
* Internal API for initializing base request in BaseInteractionClient (msal-browser)
|
|
4001
|
+
*/
|
|
4002
|
+
InitializeBaseRequest: "initializeBaseRequest",
|
|
4003
|
+
/**
|
|
4004
|
+
* Internal API for initializing silent request in SilentCacheClient (msal-browser)
|
|
4005
|
+
*/
|
|
4006
|
+
InitializeSilentRequest: "initializeSilentRequest",
|
|
4007
|
+
InitializeClientApplication: "initializeClientApplication",
|
|
4008
|
+
/**
|
|
4009
|
+
* Helper function in SilentIframeClient class (msal-browser).
|
|
4010
|
+
*/
|
|
4011
|
+
SilentIframeClientTokenHelper: "silentIframeClientTokenHelper",
|
|
4012
|
+
/**
|
|
4013
|
+
* SilentHandler
|
|
4014
|
+
*/
|
|
4015
|
+
SilentHandlerInitiateAuthRequest: "silentHandlerInitiateAuthRequest",
|
|
4016
|
+
SilentHandlerMonitorIframeForHash: "silentHandlerMonitorIframeForHash",
|
|
4017
|
+
SilentHandlerLoadFrame: "silentHandlerLoadFrame",
|
|
4018
|
+
/**
|
|
4019
|
+
* Helper functions in StandardInteractionClient class (msal-browser)
|
|
4020
|
+
*/
|
|
4021
|
+
StandardInteractionClientCreateAuthCodeClient: "standardInteractionClientCreateAuthCodeClient",
|
|
4022
|
+
StandardInteractionClientGetClientConfiguration: "standardInteractionClientGetClientConfiguration",
|
|
4023
|
+
StandardInteractionClientInitializeAuthorizationRequest: "standardInteractionClientInitializeAuthorizationRequest",
|
|
4024
|
+
StandardInteractionClientInitializeAuthorizationCodeRequest: "standardInteractionClientInitializeAuthorizationCodeRequest",
|
|
4025
|
+
/**
|
|
4026
|
+
* getAuthCodeUrl API (msal-browser and msal-node).
|
|
4027
|
+
*/
|
|
4028
|
+
GetAuthCodeUrl: "getAuthCodeUrl",
|
|
4029
|
+
/**
|
|
4030
|
+
* Functions from InteractionHandler (msal-browser)
|
|
4031
|
+
*/
|
|
4032
|
+
HandleCodeResponseFromServer: "handleCodeResponseFromServer",
|
|
4033
|
+
HandleCodeResponseFromHash: "handleCodeResponseFromHash",
|
|
4034
|
+
UpdateTokenEndpointAuthority: "updateTokenEndpointAuthority",
|
|
4035
|
+
/**
|
|
4036
|
+
* APIs in Authorization Code Client (msal-common)
|
|
4037
|
+
*/
|
|
4038
|
+
AuthClientAcquireToken: "authClientAcquireToken",
|
|
4039
|
+
AuthClientExecuteTokenRequest: "authClientExecuteTokenRequest",
|
|
4040
|
+
AuthClientCreateTokenRequestBody: "authClientCreateTokenRequestBody",
|
|
4041
|
+
AuthClientCreateQueryString: "authClientCreateQueryString",
|
|
4042
|
+
/**
|
|
4043
|
+
* Generate functions in PopTokenGenerator (msal-common)
|
|
4044
|
+
*/
|
|
4045
|
+
PopTokenGenerateCnf: "popTokenGenerateCnf",
|
|
4046
|
+
PopTokenGenerateKid: "popTokenGenerateKid",
|
|
4047
|
+
/**
|
|
4048
|
+
* handleServerTokenResponse API in ResponseHandler (msal-common)
|
|
4049
|
+
*/
|
|
4050
|
+
HandleServerTokenResponse: "handleServerTokenResponse",
|
|
4051
|
+
/**
|
|
4052
|
+
* Authority functions
|
|
4053
|
+
*/
|
|
4054
|
+
AuthorityFactoryCreateDiscoveredInstance: "authorityFactoryCreateDiscoveredInstance",
|
|
4055
|
+
AuthorityResolveEndpointsAsync: "authorityResolveEndpointsAsync",
|
|
4056
|
+
AuthorityGetCloudDiscoveryMetadataFromNetwork: "authorityGetCloudDiscoveryMetadataFromNetwork",
|
|
4057
|
+
AuthorityUpdateCloudDiscoveryMetadata: "authorityUpdateCloudDiscoveryMetadata",
|
|
4058
|
+
AuthorityGetEndpointMetadataFromNetwork: "authorityGetEndpointMetadataFromNetwork",
|
|
4059
|
+
AuthorityUpdateEndpointMetadata: "authorityUpdateEndpointMetadata",
|
|
4060
|
+
AuthorityUpdateMetadataWithRegionalInformation: "authorityUpdateMetadataWithRegionalInformation",
|
|
4061
|
+
/**
|
|
4062
|
+
* Region Discovery functions
|
|
4063
|
+
*/
|
|
4064
|
+
RegionDiscoveryDetectRegion: "regionDiscoveryDetectRegion",
|
|
4065
|
+
RegionDiscoveryGetRegionFromIMDS: "regionDiscoveryGetRegionFromIMDS",
|
|
4066
|
+
RegionDiscoveryGetCurrentVersion: "regionDiscoveryGetCurrentVersion",
|
|
4067
|
+
AcquireTokenByCodeAsync: "acquireTokenByCodeAsync",
|
|
4068
|
+
GetEndpointMetadataFromNetwork: "getEndpointMetadataFromNetwork",
|
|
4069
|
+
GetCloudDiscoveryMetadataFromNetworkMeasurement: "getCloudDiscoveryMetadataFromNetworkMeasurement",
|
|
4070
|
+
HandleRedirectPromiseMeasurement: "handleRedirectPromiseMeasurement",
|
|
4071
|
+
UpdateCloudDiscoveryMetadataMeasurement: "updateCloudDiscoveryMetadataMeasurement",
|
|
4072
|
+
UsernamePasswordClientAcquireToken: "usernamePasswordClientAcquireToken",
|
|
4073
|
+
NativeMessageHandlerHandshake: "nativeMessageHandlerHandshake",
|
|
4074
|
+
NativeGenerateAuthResult: "nativeGenerateAuthResult",
|
|
4075
|
+
/**
|
|
4076
|
+
* Cache operations
|
|
4077
|
+
*/
|
|
4078
|
+
ClearTokensAndKeysWithClaims: "clearTokensAndKeysWithClaims",
|
|
4079
|
+
};
|
|
4080
|
+
/**
|
|
4081
|
+
* State of the performance event.
|
|
4082
|
+
*
|
|
4083
|
+
* @export
|
|
4084
|
+
* @enum {number}
|
|
4085
|
+
*/
|
|
4086
|
+
const PerformanceEventStatus = {
|
|
4087
|
+
NotStarted: 0,
|
|
4088
|
+
InProgress: 1,
|
|
4089
|
+
Completed: 2,
|
|
4090
|
+
};
|
|
4091
|
+
const IntFields = new Set([
|
|
4092
|
+
"accessTokenSize",
|
|
4093
|
+
"durationMs",
|
|
4094
|
+
"idTokenSize",
|
|
4095
|
+
"matsSilentStatus",
|
|
4096
|
+
"matsHttpStatus",
|
|
4097
|
+
"refreshTokenSize",
|
|
4098
|
+
"queuedTimeMs",
|
|
4099
|
+
"startTimeMs",
|
|
4100
|
+
"status",
|
|
4101
|
+
]);
|
|
4102
|
+
|
|
4103
|
+
/*
|
|
4104
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4105
|
+
* Licensed under the MIT License.
|
|
4106
|
+
*/
|
|
4107
|
+
/**
|
|
4108
|
+
* Base application class which will construct requests to send to and handle responses from the Microsoft STS using the authorization code flow.
|
|
4109
|
+
* @internal
|
|
4110
|
+
*/
|
|
4111
|
+
class BaseClient {
|
|
4112
|
+
constructor(configuration, performanceClient) {
|
|
4113
|
+
// Set the configuration
|
|
4114
|
+
this.config = buildClientConfiguration(configuration);
|
|
4115
|
+
// Initialize the logger
|
|
4116
|
+
this.logger = new Logger(this.config.loggerOptions, name, version);
|
|
4117
|
+
// Initialize crypto
|
|
4118
|
+
this.cryptoUtils = this.config.cryptoInterface;
|
|
4119
|
+
// Initialize storage interface
|
|
3899
4120
|
this.cacheManager = this.config.storageInterface;
|
|
3900
4121
|
// Set the network interface
|
|
3901
4122
|
this.networkClient = this.config.networkInterface;
|
|
@@ -3940,8 +4161,13 @@ class BaseClient {
|
|
|
3940
4161
|
* @param headers
|
|
3941
4162
|
* @param thumbprint
|
|
3942
4163
|
*/
|
|
3943
|
-
async executePostToTokenEndpoint(tokenEndpoint, queryString, headers, thumbprint) {
|
|
4164
|
+
async executePostToTokenEndpoint(tokenEndpoint, queryString, headers, thumbprint, correlationId) {
|
|
4165
|
+
this.performanceClient?.addQueueMeasurement(PerformanceEvents.BaseClientCreateTokenRequestHeaders, correlationId);
|
|
3944
4166
|
const response = await this.networkManager.sendPostRequest(thumbprint, tokenEndpoint, { body: queryString, headers: headers });
|
|
4167
|
+
this.performanceClient?.addFields({
|
|
4168
|
+
refreshTokenSize: response.body.refresh_token?.length || 0,
|
|
4169
|
+
httpVerToken: response.headers?.[HeaderNames.X_MS_HTTP_VERSION] || "",
|
|
4170
|
+
}, correlationId);
|
|
3945
4171
|
if (this.config.serverTelemetryManager &&
|
|
3946
4172
|
response.status < 500 &&
|
|
3947
4173
|
response.status !== 429) {
|
|
@@ -4253,583 +4479,73 @@ class AccessTokenEntity extends CredentialEntity {
|
|
|
4253
4479
|
* @param expiresOn
|
|
4254
4480
|
* @param extExpiresOn
|
|
4255
4481
|
*/
|
|
4256
|
-
static createAccessTokenEntity(homeAccountId, environment, accessToken, clientId, tenantId, scopes, expiresOn, extExpiresOn, cryptoUtils, refreshOn, tokenType, userAssertionHash, keyId, requestedClaims, requestedClaimsHash) {
|
|
4257
|
-
const atEntity = new AccessTokenEntity();
|
|
4258
|
-
atEntity.homeAccountId = homeAccountId;
|
|
4259
|
-
atEntity.credentialType = CredentialType.ACCESS_TOKEN;
|
|
4260
|
-
atEntity.secret = accessToken;
|
|
4261
|
-
const currentTime = TimeUtils.nowSeconds();
|
|
4262
|
-
atEntity.cachedAt = currentTime.toString();
|
|
4263
|
-
/*
|
|
4264
|
-
* Token expiry time.
|
|
4265
|
-
* This value should be calculated based on the current UTC time measured locally and the value expires_in Represented as a string in JSON.
|
|
4266
|
-
*/
|
|
4267
|
-
atEntity.expiresOn = expiresOn.toString();
|
|
4268
|
-
atEntity.extendedExpiresOn = extExpiresOn.toString();
|
|
4269
|
-
if (refreshOn) {
|
|
4270
|
-
atEntity.refreshOn = refreshOn.toString();
|
|
4271
|
-
}
|
|
4272
|
-
atEntity.environment = environment;
|
|
4273
|
-
atEntity.clientId = clientId;
|
|
4274
|
-
atEntity.realm = tenantId;
|
|
4275
|
-
atEntity.target = scopes;
|
|
4276
|
-
atEntity.userAssertionHash = userAssertionHash;
|
|
4277
|
-
atEntity.tokenType = StringUtils.isEmpty(tokenType)
|
|
4278
|
-
? AuthenticationScheme.BEARER
|
|
4279
|
-
: tokenType;
|
|
4280
|
-
if (requestedClaims) {
|
|
4281
|
-
atEntity.requestedClaims = requestedClaims;
|
|
4282
|
-
atEntity.requestedClaimsHash = requestedClaimsHash;
|
|
4283
|
-
}
|
|
4284
|
-
/*
|
|
4285
|
-
* Create Access Token With Auth Scheme instead of regular access token
|
|
4286
|
-
* Cast to lower to handle "bearer" from ADFS
|
|
4287
|
-
*/
|
|
4288
|
-
if (atEntity.tokenType?.toLowerCase() !==
|
|
4289
|
-
AuthenticationScheme.BEARER.toLowerCase()) {
|
|
4290
|
-
atEntity.credentialType =
|
|
4291
|
-
CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;
|
|
4292
|
-
switch (atEntity.tokenType) {
|
|
4293
|
-
case AuthenticationScheme.POP:
|
|
4294
|
-
// Make sure keyId is present and add it to credential
|
|
4295
|
-
const tokenClaims = AuthToken.extractTokenClaims(accessToken, cryptoUtils);
|
|
4296
|
-
if (!tokenClaims?.cnf?.kid) {
|
|
4297
|
-
throw ClientAuthError.createTokenClaimsRequiredError();
|
|
4298
|
-
}
|
|
4299
|
-
atEntity.keyId = tokenClaims.cnf.kid;
|
|
4300
|
-
break;
|
|
4301
|
-
case AuthenticationScheme.SSH:
|
|
4302
|
-
atEntity.keyId = keyId;
|
|
4303
|
-
}
|
|
4304
|
-
}
|
|
4305
|
-
return atEntity;
|
|
4306
|
-
}
|
|
4307
|
-
/**
|
|
4308
|
-
* Validates an entity: checks for all expected params
|
|
4309
|
-
* @param entity
|
|
4310
|
-
*/
|
|
4311
|
-
static isAccessTokenEntity(entity) {
|
|
4312
|
-
if (!entity) {
|
|
4313
|
-
return false;
|
|
4314
|
-
}
|
|
4315
|
-
return (entity.hasOwnProperty("homeAccountId") &&
|
|
4316
|
-
entity.hasOwnProperty("environment") &&
|
|
4317
|
-
entity.hasOwnProperty("credentialType") &&
|
|
4318
|
-
entity.hasOwnProperty("realm") &&
|
|
4319
|
-
entity.hasOwnProperty("clientId") &&
|
|
4320
|
-
entity.hasOwnProperty("secret") &&
|
|
4321
|
-
entity.hasOwnProperty("target") &&
|
|
4322
|
-
(entity["credentialType"] === CredentialType.ACCESS_TOKEN ||
|
|
4323
|
-
entity["credentialType"] ===
|
|
4324
|
-
CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME));
|
|
4325
|
-
}
|
|
4326
|
-
}
|
|
4327
|
-
|
|
4328
|
-
/*
|
|
4329
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4330
|
-
* Licensed under the MIT License.
|
|
4331
|
-
*/
|
|
4332
|
-
/**
|
|
4333
|
-
* REFRESH_TOKEN Cache
|
|
4334
|
-
*
|
|
4335
|
-
* Key:Value Schema:
|
|
4336
|
-
*
|
|
4337
|
-
* Key Example: uid.utid-login.microsoftonline.com-refreshtoken-clientId--
|
|
4338
|
-
*
|
|
4339
|
-
* Value:
|
|
4340
|
-
* {
|
|
4341
|
-
* homeAccountId: home account identifier for the auth scheme,
|
|
4342
|
-
* environment: entity that issued the token, represented as a full host
|
|
4343
|
-
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
|
4344
|
-
* clientId: client ID of the application
|
|
4345
|
-
* secret: Actual credential as a string
|
|
4346
|
-
* familyId: Family ID identifier, '1' represents Microsoft Family
|
|
4347
|
-
* realm: Full tenant or organizational identifier that the account belongs to
|
|
4348
|
-
* target: Permissions that are included in the token, or for refresh tokens, the resource identifier.
|
|
4349
|
-
* }
|
|
4350
|
-
*/
|
|
4351
|
-
class RefreshTokenEntity extends CredentialEntity {
|
|
4352
|
-
/**
|
|
4353
|
-
* Create RefreshTokenEntity
|
|
4354
|
-
* @param homeAccountId
|
|
4355
|
-
* @param authenticationResult
|
|
4356
|
-
* @param clientId
|
|
4357
|
-
* @param authority
|
|
4358
|
-
*/
|
|
4359
|
-
static createRefreshTokenEntity(homeAccountId, environment, refreshToken, clientId, familyId, userAssertionHash) {
|
|
4360
|
-
const rtEntity = new RefreshTokenEntity();
|
|
4361
|
-
rtEntity.clientId = clientId;
|
|
4362
|
-
rtEntity.credentialType = CredentialType.REFRESH_TOKEN;
|
|
4363
|
-
rtEntity.environment = environment;
|
|
4364
|
-
rtEntity.homeAccountId = homeAccountId;
|
|
4365
|
-
rtEntity.secret = refreshToken;
|
|
4366
|
-
rtEntity.userAssertionHash = userAssertionHash;
|
|
4367
|
-
if (familyId)
|
|
4368
|
-
rtEntity.familyId = familyId;
|
|
4369
|
-
return rtEntity;
|
|
4370
|
-
}
|
|
4371
|
-
/**
|
|
4372
|
-
* Validates an entity: checks for all expected params
|
|
4373
|
-
* @param entity
|
|
4374
|
-
*/
|
|
4375
|
-
static isRefreshTokenEntity(entity) {
|
|
4376
|
-
if (!entity) {
|
|
4377
|
-
return false;
|
|
4378
|
-
}
|
|
4379
|
-
return (entity.hasOwnProperty("homeAccountId") &&
|
|
4380
|
-
entity.hasOwnProperty("environment") &&
|
|
4381
|
-
entity.hasOwnProperty("credentialType") &&
|
|
4382
|
-
entity.hasOwnProperty("clientId") &&
|
|
4383
|
-
entity.hasOwnProperty("secret") &&
|
|
4384
|
-
entity["credentialType"] === CredentialType.REFRESH_TOKEN);
|
|
4385
|
-
}
|
|
4386
|
-
}
|
|
4387
|
-
|
|
4388
|
-
/*
|
|
4389
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4390
|
-
* Licensed under the MIT License.
|
|
4391
|
-
*/
|
|
4392
|
-
/**
|
|
4393
|
-
* InteractionRequiredServerErrorMessage contains string constants used by error codes and messages returned by the server indicating interaction is required
|
|
4394
|
-
*/
|
|
4395
|
-
const InteractionRequiredServerErrorMessage = [
|
|
4396
|
-
"interaction_required",
|
|
4397
|
-
"consent_required",
|
|
4398
|
-
"login_required",
|
|
4399
|
-
];
|
|
4400
|
-
const InteractionRequiredAuthSubErrorMessage = [
|
|
4401
|
-
"message_only",
|
|
4402
|
-
"additional_action",
|
|
4403
|
-
"basic_action",
|
|
4404
|
-
"user_password_expired",
|
|
4405
|
-
"consent_required",
|
|
4406
|
-
];
|
|
4407
|
-
/**
|
|
4408
|
-
* Interaction required errors defined by the SDK
|
|
4409
|
-
*/
|
|
4410
|
-
const InteractionRequiredAuthErrorMessage = {
|
|
4411
|
-
noTokensFoundError: {
|
|
4412
|
-
code: "no_tokens_found",
|
|
4413
|
-
desc: "No refresh token found in the cache. Please sign-in.",
|
|
4414
|
-
},
|
|
4415
|
-
native_account_unavailable: {
|
|
4416
|
-
code: "native_account_unavailable",
|
|
4417
|
-
desc: "The requested account is not available in the native broker. It may have been deleted or logged out. Please sign-in again using an interactive API.",
|
|
4418
|
-
},
|
|
4419
|
-
};
|
|
4420
|
-
/**
|
|
4421
|
-
* Error thrown when user interaction is required.
|
|
4422
|
-
*/
|
|
4423
|
-
class InteractionRequiredAuthError extends AuthError {
|
|
4424
|
-
constructor(errorCode, errorMessage, subError, timestamp, traceId, correlationId, claims) {
|
|
4425
|
-
super(errorCode, errorMessage, subError);
|
|
4426
|
-
Object.setPrototypeOf(this, InteractionRequiredAuthError.prototype);
|
|
4427
|
-
this.timestamp = timestamp || Constants.EMPTY_STRING;
|
|
4428
|
-
this.traceId = traceId || Constants.EMPTY_STRING;
|
|
4429
|
-
this.correlationId = correlationId || Constants.EMPTY_STRING;
|
|
4430
|
-
this.claims = claims || Constants.EMPTY_STRING;
|
|
4431
|
-
this.name = "InteractionRequiredAuthError";
|
|
4432
|
-
}
|
|
4433
|
-
/**
|
|
4434
|
-
* Helper function used to determine if an error thrown by the server requires interaction to resolve
|
|
4435
|
-
* @param errorCode
|
|
4436
|
-
* @param errorString
|
|
4437
|
-
* @param subError
|
|
4438
|
-
*/
|
|
4439
|
-
static isInteractionRequiredError(errorCode, errorString, subError) {
|
|
4440
|
-
const isInteractionRequiredErrorCode = !!errorCode &&
|
|
4441
|
-
InteractionRequiredServerErrorMessage.indexOf(errorCode) > -1;
|
|
4442
|
-
const isInteractionRequiredSubError = !!subError &&
|
|
4443
|
-
InteractionRequiredAuthSubErrorMessage.indexOf(subError) > -1;
|
|
4444
|
-
const isInteractionRequiredErrorDesc = !!errorString &&
|
|
4445
|
-
InteractionRequiredServerErrorMessage.some((irErrorCode) => {
|
|
4446
|
-
return errorString.indexOf(irErrorCode) > -1;
|
|
4447
|
-
});
|
|
4448
|
-
return (isInteractionRequiredErrorCode ||
|
|
4449
|
-
isInteractionRequiredErrorDesc ||
|
|
4450
|
-
isInteractionRequiredSubError);
|
|
4451
|
-
}
|
|
4452
|
-
/**
|
|
4453
|
-
* Creates an error thrown when the authorization code required for a token request is null or empty.
|
|
4454
|
-
*/
|
|
4455
|
-
static createNoTokensFoundError() {
|
|
4456
|
-
return new InteractionRequiredAuthError(InteractionRequiredAuthErrorMessage.noTokensFoundError.code, InteractionRequiredAuthErrorMessage.noTokensFoundError.desc);
|
|
4457
|
-
}
|
|
4458
|
-
/**
|
|
4459
|
-
* Creates an error thrown when the native broker returns ACCOUNT_UNAVAILABLE status, indicating that the account was removed and interactive sign-in is required
|
|
4460
|
-
* @returns
|
|
4461
|
-
*/
|
|
4462
|
-
static createNativeAccountUnavailableError() {
|
|
4463
|
-
return new InteractionRequiredAuthError(InteractionRequiredAuthErrorMessage.native_account_unavailable.code, InteractionRequiredAuthErrorMessage.native_account_unavailable.desc);
|
|
4464
|
-
}
|
|
4465
|
-
}
|
|
4466
|
-
|
|
4467
|
-
/*
|
|
4468
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4469
|
-
* Licensed under the MIT License.
|
|
4470
|
-
*/
|
|
4471
|
-
/** @internal */
|
|
4472
|
-
class CacheRecord {
|
|
4473
|
-
constructor(accountEntity, idTokenEntity, accessTokenEntity, refreshTokenEntity, appMetadataEntity) {
|
|
4474
|
-
this.account = accountEntity || null;
|
|
4475
|
-
this.idToken = idTokenEntity || null;
|
|
4476
|
-
this.accessToken = accessTokenEntity || null;
|
|
4477
|
-
this.refreshToken = refreshTokenEntity || null;
|
|
4478
|
-
this.appMetadata = appMetadataEntity || null;
|
|
4479
|
-
}
|
|
4480
|
-
}
|
|
4481
|
-
|
|
4482
|
-
/*
|
|
4483
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4484
|
-
* Licensed under the MIT License.
|
|
4485
|
-
*/
|
|
4486
|
-
/**
|
|
4487
|
-
* Class which provides helpers for OAuth 2.0 protocol specific values
|
|
4488
|
-
*/
|
|
4489
|
-
class ProtocolUtils {
|
|
4490
|
-
/**
|
|
4491
|
-
* Appends user state with random guid, or returns random guid.
|
|
4492
|
-
* @param userState
|
|
4493
|
-
* @param randomGuid
|
|
4494
|
-
*/
|
|
4495
|
-
static setRequestState(cryptoObj, userState, meta) {
|
|
4496
|
-
const libraryState = ProtocolUtils.generateLibraryState(cryptoObj, meta);
|
|
4497
|
-
return !StringUtils.isEmpty(userState)
|
|
4498
|
-
? `${libraryState}${Constants.RESOURCE_DELIM}${userState}`
|
|
4499
|
-
: libraryState;
|
|
4500
|
-
}
|
|
4501
|
-
/**
|
|
4502
|
-
* Generates the state value used by the common library.
|
|
4503
|
-
* @param randomGuid
|
|
4504
|
-
* @param cryptoObj
|
|
4505
|
-
*/
|
|
4506
|
-
static generateLibraryState(cryptoObj, meta) {
|
|
4507
|
-
if (!cryptoObj) {
|
|
4508
|
-
throw ClientAuthError.createNoCryptoObjectError("generateLibraryState");
|
|
4509
|
-
}
|
|
4510
|
-
// Create a state object containing a unique id and the timestamp of the request creation
|
|
4511
|
-
const stateObj = {
|
|
4512
|
-
id: cryptoObj.createNewGuid(),
|
|
4513
|
-
};
|
|
4514
|
-
if (meta) {
|
|
4515
|
-
stateObj.meta = meta;
|
|
4516
|
-
}
|
|
4517
|
-
const stateString = JSON.stringify(stateObj);
|
|
4518
|
-
return cryptoObj.base64Encode(stateString);
|
|
4519
|
-
}
|
|
4520
|
-
/**
|
|
4521
|
-
* Parses the state into the RequestStateObject, which contains the LibraryState info and the state passed by the user.
|
|
4522
|
-
* @param state
|
|
4523
|
-
* @param cryptoObj
|
|
4524
|
-
*/
|
|
4525
|
-
static parseRequestState(cryptoObj, state) {
|
|
4526
|
-
if (!cryptoObj) {
|
|
4527
|
-
throw ClientAuthError.createNoCryptoObjectError("parseRequestState");
|
|
4528
|
-
}
|
|
4529
|
-
if (StringUtils.isEmpty(state)) {
|
|
4530
|
-
throw ClientAuthError.createInvalidStateError(state, "Null, undefined or empty state");
|
|
4531
|
-
}
|
|
4532
|
-
try {
|
|
4533
|
-
// Split the state between library state and user passed state and decode them separately
|
|
4534
|
-
const splitState = state.split(Constants.RESOURCE_DELIM);
|
|
4535
|
-
const libraryState = splitState[0];
|
|
4536
|
-
const userState = splitState.length > 1
|
|
4537
|
-
? splitState.slice(1).join(Constants.RESOURCE_DELIM)
|
|
4538
|
-
: Constants.EMPTY_STRING;
|
|
4539
|
-
const libraryStateString = cryptoObj.base64Decode(libraryState);
|
|
4540
|
-
const libraryStateObj = JSON.parse(libraryStateString);
|
|
4541
|
-
return {
|
|
4542
|
-
userRequestState: !StringUtils.isEmpty(userState)
|
|
4543
|
-
? userState
|
|
4544
|
-
: Constants.EMPTY_STRING,
|
|
4545
|
-
libraryState: libraryStateObj,
|
|
4546
|
-
};
|
|
4547
|
-
}
|
|
4548
|
-
catch (e) {
|
|
4549
|
-
throw ClientAuthError.createInvalidStateError(state, e);
|
|
4550
|
-
}
|
|
4551
|
-
}
|
|
4552
|
-
}
|
|
4553
|
-
|
|
4554
|
-
/*
|
|
4555
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4556
|
-
* Licensed under the MIT License.
|
|
4557
|
-
*/
|
|
4558
|
-
/**
|
|
4559
|
-
* Url object class which can perform various transformations on url strings.
|
|
4560
|
-
*/
|
|
4561
|
-
class UrlString {
|
|
4562
|
-
get urlString() {
|
|
4563
|
-
return this._urlString;
|
|
4564
|
-
}
|
|
4565
|
-
constructor(url) {
|
|
4566
|
-
this._urlString = url;
|
|
4567
|
-
if (StringUtils.isEmpty(this._urlString)) {
|
|
4568
|
-
// Throws error if url is empty
|
|
4569
|
-
throw ClientConfigurationError.createUrlEmptyError();
|
|
4570
|
-
}
|
|
4571
|
-
if (StringUtils.isEmpty(this.getHash())) {
|
|
4572
|
-
this._urlString = UrlString.canonicalizeUri(url);
|
|
4573
|
-
}
|
|
4574
|
-
}
|
|
4575
|
-
/**
|
|
4576
|
-
* Ensure urls are lower case and end with a / character.
|
|
4577
|
-
* @param url
|
|
4578
|
-
*/
|
|
4579
|
-
static canonicalizeUri(url) {
|
|
4580
|
-
if (url) {
|
|
4581
|
-
let lowerCaseUrl = url.toLowerCase();
|
|
4582
|
-
if (StringUtils.endsWith(lowerCaseUrl, "?")) {
|
|
4583
|
-
lowerCaseUrl = lowerCaseUrl.slice(0, -1);
|
|
4584
|
-
}
|
|
4585
|
-
else if (StringUtils.endsWith(lowerCaseUrl, "?/")) {
|
|
4586
|
-
lowerCaseUrl = lowerCaseUrl.slice(0, -2);
|
|
4587
|
-
}
|
|
4588
|
-
if (!StringUtils.endsWith(lowerCaseUrl, "/")) {
|
|
4589
|
-
lowerCaseUrl += "/";
|
|
4590
|
-
}
|
|
4591
|
-
return lowerCaseUrl;
|
|
4592
|
-
}
|
|
4593
|
-
return url;
|
|
4594
|
-
}
|
|
4595
|
-
/**
|
|
4596
|
-
* Throws if urlString passed is not a valid authority URI string.
|
|
4597
|
-
*/
|
|
4598
|
-
validateAsUri() {
|
|
4599
|
-
// Attempts to parse url for uri components
|
|
4600
|
-
let components;
|
|
4601
|
-
try {
|
|
4602
|
-
components = this.getUrlComponents();
|
|
4603
|
-
}
|
|
4604
|
-
catch (e) {
|
|
4605
|
-
throw ClientConfigurationError.createUrlParseError(e);
|
|
4606
|
-
}
|
|
4607
|
-
// Throw error if URI or path segments are not parseable.
|
|
4608
|
-
if (!components.HostNameAndPort || !components.PathSegments) {
|
|
4609
|
-
throw ClientConfigurationError.createUrlParseError(`Given url string: ${this.urlString}`);
|
|
4610
|
-
}
|
|
4611
|
-
// Throw error if uri is insecure.
|
|
4612
|
-
if (!components.Protocol ||
|
|
4613
|
-
components.Protocol.toLowerCase() !== "https:") {
|
|
4614
|
-
throw ClientConfigurationError.createInsecureAuthorityUriError(this.urlString);
|
|
4615
|
-
}
|
|
4616
|
-
}
|
|
4617
|
-
/**
|
|
4618
|
-
* Given a url and a query string return the url with provided query string appended
|
|
4619
|
-
* @param url
|
|
4620
|
-
* @param queryString
|
|
4621
|
-
*/
|
|
4622
|
-
static appendQueryString(url, queryString) {
|
|
4623
|
-
if (StringUtils.isEmpty(queryString)) {
|
|
4624
|
-
return url;
|
|
4625
|
-
}
|
|
4626
|
-
return url.indexOf("?") < 0
|
|
4627
|
-
? `${url}?${queryString}`
|
|
4628
|
-
: `${url}&${queryString}`;
|
|
4629
|
-
}
|
|
4630
|
-
/**
|
|
4631
|
-
* Returns a url with the hash removed
|
|
4632
|
-
* @param url
|
|
4633
|
-
*/
|
|
4634
|
-
static removeHashFromUrl(url) {
|
|
4635
|
-
return UrlString.canonicalizeUri(url.split("#")[0]);
|
|
4636
|
-
}
|
|
4637
|
-
/**
|
|
4638
|
-
* Given a url like https://a:b/common/d?e=f#g, and a tenantId, returns https://a:b/tenantId/d
|
|
4639
|
-
* @param href The url
|
|
4640
|
-
* @param tenantId The tenant id to replace
|
|
4641
|
-
*/
|
|
4642
|
-
replaceTenantPath(tenantId) {
|
|
4643
|
-
const urlObject = this.getUrlComponents();
|
|
4644
|
-
const pathArray = urlObject.PathSegments;
|
|
4645
|
-
if (tenantId &&
|
|
4646
|
-
pathArray.length !== 0 &&
|
|
4647
|
-
(pathArray[0] === AADAuthorityConstants.COMMON ||
|
|
4648
|
-
pathArray[0] === AADAuthorityConstants.ORGANIZATIONS)) {
|
|
4649
|
-
pathArray[0] = tenantId;
|
|
4650
|
-
}
|
|
4651
|
-
return UrlString.constructAuthorityUriFromObject(urlObject);
|
|
4652
|
-
}
|
|
4653
|
-
/**
|
|
4654
|
-
* Returns the anchor part(#) of the URL
|
|
4655
|
-
*/
|
|
4656
|
-
getHash() {
|
|
4657
|
-
return UrlString.parseHash(this.urlString);
|
|
4658
|
-
}
|
|
4659
|
-
/**
|
|
4660
|
-
* Parses out the components from a url string.
|
|
4661
|
-
* @returns An object with the various components. Please cache this value insted of calling this multiple times on the same url.
|
|
4662
|
-
*/
|
|
4663
|
-
getUrlComponents() {
|
|
4664
|
-
// https://gist.github.com/curtisz/11139b2cfcaef4a261e0
|
|
4665
|
-
const regEx = RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
|
|
4666
|
-
// If url string does not match regEx, we throw an error
|
|
4667
|
-
const match = this.urlString.match(regEx);
|
|
4668
|
-
if (!match) {
|
|
4669
|
-
throw ClientConfigurationError.createUrlParseError(`Given url string: ${this.urlString}`);
|
|
4670
|
-
}
|
|
4671
|
-
// Url component object
|
|
4672
|
-
const urlComponents = {
|
|
4673
|
-
Protocol: match[1],
|
|
4674
|
-
HostNameAndPort: match[4],
|
|
4675
|
-
AbsolutePath: match[5],
|
|
4676
|
-
QueryString: match[7],
|
|
4677
|
-
};
|
|
4678
|
-
let pathSegments = urlComponents.AbsolutePath.split("/");
|
|
4679
|
-
pathSegments = pathSegments.filter((val) => val && val.length > 0); // remove empty elements
|
|
4680
|
-
urlComponents.PathSegments = pathSegments;
|
|
4681
|
-
if (!StringUtils.isEmpty(urlComponents.QueryString) &&
|
|
4682
|
-
urlComponents.QueryString.endsWith("/")) {
|
|
4683
|
-
urlComponents.QueryString = urlComponents.QueryString.substring(0, urlComponents.QueryString.length - 1);
|
|
4684
|
-
}
|
|
4685
|
-
return urlComponents;
|
|
4686
|
-
}
|
|
4687
|
-
static getDomainFromUrl(url) {
|
|
4688
|
-
const regEx = RegExp("^([^:/?#]+://)?([^/?#]*)");
|
|
4689
|
-
const match = url.match(regEx);
|
|
4690
|
-
if (!match) {
|
|
4691
|
-
throw ClientConfigurationError.createUrlParseError(`Given url string: ${url}`);
|
|
4692
|
-
}
|
|
4693
|
-
return match[2];
|
|
4694
|
-
}
|
|
4695
|
-
static getAbsoluteUrl(relativeUrl, baseUrl) {
|
|
4696
|
-
if (relativeUrl[0] === Constants.FORWARD_SLASH) {
|
|
4697
|
-
const url = new UrlString(baseUrl);
|
|
4698
|
-
const baseComponents = url.getUrlComponents();
|
|
4699
|
-
return (baseComponents.Protocol +
|
|
4700
|
-
"//" +
|
|
4701
|
-
baseComponents.HostNameAndPort +
|
|
4702
|
-
relativeUrl);
|
|
4703
|
-
}
|
|
4704
|
-
return relativeUrl;
|
|
4705
|
-
}
|
|
4706
|
-
/**
|
|
4707
|
-
* Parses hash string from given string. Returns empty string if no hash symbol is found.
|
|
4708
|
-
* @param hashString
|
|
4709
|
-
*/
|
|
4710
|
-
static parseHash(hashString) {
|
|
4711
|
-
const hashIndex1 = hashString.indexOf("#");
|
|
4712
|
-
const hashIndex2 = hashString.indexOf("#/");
|
|
4713
|
-
if (hashIndex2 > -1) {
|
|
4714
|
-
return hashString.substring(hashIndex2 + 2);
|
|
4715
|
-
}
|
|
4716
|
-
else if (hashIndex1 > -1) {
|
|
4717
|
-
return hashString.substring(hashIndex1 + 1);
|
|
4718
|
-
}
|
|
4719
|
-
return Constants.EMPTY_STRING;
|
|
4720
|
-
}
|
|
4721
|
-
/**
|
|
4722
|
-
* Parses query string from given string. Returns empty string if no query symbol is found.
|
|
4723
|
-
* @param queryString
|
|
4724
|
-
*/
|
|
4725
|
-
static parseQueryString(queryString) {
|
|
4726
|
-
const queryIndex1 = queryString.indexOf("?");
|
|
4727
|
-
const queryIndex2 = queryString.indexOf("/?");
|
|
4728
|
-
if (queryIndex2 > -1) {
|
|
4729
|
-
return queryString.substring(queryIndex2 + 2);
|
|
4730
|
-
}
|
|
4731
|
-
else if (queryIndex1 > -1) {
|
|
4732
|
-
return queryString.substring(queryIndex1 + 1);
|
|
4733
|
-
}
|
|
4734
|
-
return Constants.EMPTY_STRING;
|
|
4735
|
-
}
|
|
4736
|
-
/**
|
|
4737
|
-
* Parses query server response string from given string.
|
|
4738
|
-
* Extract hash between '?code=' and '#' if trailing '# is present.
|
|
4739
|
-
* Returns empty string if no query symbol is found.
|
|
4740
|
-
* @param queryString
|
|
4741
|
-
*/
|
|
4742
|
-
static parseQueryServerResponse(queryString) {
|
|
4743
|
-
const queryIndex1 = queryString.indexOf("?code");
|
|
4744
|
-
const queryIndex2 = queryString.indexOf("/?code");
|
|
4745
|
-
const hashIndex = queryString.indexOf("#");
|
|
4746
|
-
if (queryIndex2 > -1 && hashIndex > -1) {
|
|
4747
|
-
return queryString.substring(queryIndex2 + 2, hashIndex);
|
|
4748
|
-
}
|
|
4749
|
-
else if (queryIndex2 > -1) {
|
|
4750
|
-
return queryString.substring(queryIndex2 + 2);
|
|
4751
|
-
}
|
|
4752
|
-
else if (queryIndex1 > -1 && hashIndex > -1) {
|
|
4753
|
-
return queryString.substring(queryIndex1 + 1, hashIndex);
|
|
4754
|
-
}
|
|
4755
|
-
else if (queryIndex1 > -1) {
|
|
4756
|
-
return queryString.substring(queryIndex1 + 1);
|
|
4757
|
-
}
|
|
4758
|
-
return Constants.EMPTY_STRING;
|
|
4759
|
-
}
|
|
4760
|
-
static constructAuthorityUriFromObject(urlObject) {
|
|
4761
|
-
return new UrlString(urlObject.Protocol +
|
|
4762
|
-
"//" +
|
|
4763
|
-
urlObject.HostNameAndPort +
|
|
4764
|
-
"/" +
|
|
4765
|
-
urlObject.PathSegments.join("/"));
|
|
4766
|
-
}
|
|
4767
|
-
/**
|
|
4768
|
-
* Returns URL hash as server auth code response object.
|
|
4769
|
-
*/
|
|
4770
|
-
static getDeserializedHash(hash) {
|
|
4771
|
-
// Check if given hash is empty
|
|
4772
|
-
if (StringUtils.isEmpty(hash)) {
|
|
4773
|
-
return {};
|
|
4774
|
-
}
|
|
4775
|
-
// Strip the # symbol if present
|
|
4776
|
-
const parsedHash = UrlString.parseHash(hash);
|
|
4777
|
-
// If # symbol was not present, above will return empty string, so give original hash value
|
|
4778
|
-
const deserializedHash = StringUtils.queryStringToObject(StringUtils.isEmpty(parsedHash) ? hash : parsedHash);
|
|
4779
|
-
// Check if deserialization didn't work
|
|
4780
|
-
if (!deserializedHash) {
|
|
4781
|
-
throw ClientAuthError.createHashNotDeserializedError(JSON.stringify(deserializedHash));
|
|
4782
|
-
}
|
|
4783
|
-
return deserializedHash;
|
|
4784
|
-
}
|
|
4785
|
-
/**
|
|
4786
|
-
* Returns URL query string as server auth code response object.
|
|
4787
|
-
*/
|
|
4788
|
-
static getDeserializedQueryString(query) {
|
|
4789
|
-
// Check if given query is empty
|
|
4790
|
-
if (StringUtils.isEmpty(query)) {
|
|
4791
|
-
return {};
|
|
4792
|
-
}
|
|
4793
|
-
// Strip the ? symbol if present
|
|
4794
|
-
const parsedQueryString = UrlString.parseQueryString(query);
|
|
4795
|
-
// If ? symbol was not present, above will return empty string, so give original query value
|
|
4796
|
-
const deserializedQueryString = StringUtils.queryStringToObject(StringUtils.isEmpty(parsedQueryString)
|
|
4797
|
-
? query
|
|
4798
|
-
: parsedQueryString);
|
|
4799
|
-
// Check if deserialization didn't work
|
|
4800
|
-
if (!deserializedQueryString) {
|
|
4801
|
-
throw ClientAuthError.createHashNotDeserializedError(JSON.stringify(deserializedQueryString));
|
|
4802
|
-
}
|
|
4803
|
-
return deserializedQueryString;
|
|
4804
|
-
}
|
|
4805
|
-
/**
|
|
4806
|
-
* Returns either deserialized query string or deserialized hash, depending on the serverResponseType
|
|
4807
|
-
* as a server auth code response object.
|
|
4808
|
-
*/
|
|
4809
|
-
static getDeserializedCodeResponse(serverResponseType, hashFragment) {
|
|
4810
|
-
const hashUrlString = new UrlString(hashFragment);
|
|
4811
|
-
let serverParams;
|
|
4812
|
-
if (serverResponseType === ServerResponseType.QUERY) {
|
|
4813
|
-
serverParams = UrlString.getDeserializedQueryString(hashFragment);
|
|
4482
|
+
static createAccessTokenEntity(homeAccountId, environment, accessToken, clientId, tenantId, scopes, expiresOn, extExpiresOn, cryptoUtils, refreshOn, tokenType, userAssertionHash, keyId, requestedClaims, requestedClaimsHash) {
|
|
4483
|
+
const atEntity = new AccessTokenEntity();
|
|
4484
|
+
atEntity.homeAccountId = homeAccountId;
|
|
4485
|
+
atEntity.credentialType = CredentialType.ACCESS_TOKEN;
|
|
4486
|
+
atEntity.secret = accessToken;
|
|
4487
|
+
const currentTime = TimeUtils.nowSeconds();
|
|
4488
|
+
atEntity.cachedAt = currentTime.toString();
|
|
4489
|
+
/*
|
|
4490
|
+
* Token expiry time.
|
|
4491
|
+
* This value should be calculated based on the current UTC time measured locally and the value expires_in Represented as a string in JSON.
|
|
4492
|
+
*/
|
|
4493
|
+
atEntity.expiresOn = expiresOn.toString();
|
|
4494
|
+
atEntity.extendedExpiresOn = extExpiresOn.toString();
|
|
4495
|
+
if (refreshOn) {
|
|
4496
|
+
atEntity.refreshOn = refreshOn.toString();
|
|
4814
4497
|
}
|
|
4815
|
-
|
|
4816
|
-
|
|
4498
|
+
atEntity.environment = environment;
|
|
4499
|
+
atEntity.clientId = clientId;
|
|
4500
|
+
atEntity.realm = tenantId;
|
|
4501
|
+
atEntity.target = scopes;
|
|
4502
|
+
atEntity.userAssertionHash = userAssertionHash;
|
|
4503
|
+
atEntity.tokenType = tokenType || AuthenticationScheme.BEARER;
|
|
4504
|
+
if (requestedClaims) {
|
|
4505
|
+
atEntity.requestedClaims = requestedClaims;
|
|
4506
|
+
atEntity.requestedClaimsHash = requestedClaimsHash;
|
|
4817
4507
|
}
|
|
4818
|
-
|
|
4508
|
+
/*
|
|
4509
|
+
* Create Access Token With Auth Scheme instead of regular access token
|
|
4510
|
+
* Cast to lower to handle "bearer" from ADFS
|
|
4511
|
+
*/
|
|
4512
|
+
if (atEntity.tokenType?.toLowerCase() !==
|
|
4513
|
+
AuthenticationScheme.BEARER.toLowerCase()) {
|
|
4514
|
+
atEntity.credentialType =
|
|
4515
|
+
CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;
|
|
4516
|
+
switch (atEntity.tokenType) {
|
|
4517
|
+
case AuthenticationScheme.POP:
|
|
4518
|
+
// Make sure keyId is present and add it to credential
|
|
4519
|
+
const tokenClaims = extractTokenClaims(accessToken, cryptoUtils.base64Decode);
|
|
4520
|
+
if (!tokenClaims?.cnf?.kid) {
|
|
4521
|
+
throw ClientAuthError.createTokenClaimsRequiredError();
|
|
4522
|
+
}
|
|
4523
|
+
atEntity.keyId = tokenClaims.cnf.kid;
|
|
4524
|
+
break;
|
|
4525
|
+
case AuthenticationScheme.SSH:
|
|
4526
|
+
atEntity.keyId = keyId;
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
return atEntity;
|
|
4819
4530
|
}
|
|
4820
4531
|
/**
|
|
4821
|
-
*
|
|
4532
|
+
* Validates an entity: checks for all expected params
|
|
4533
|
+
* @param entity
|
|
4822
4534
|
*/
|
|
4823
|
-
static
|
|
4824
|
-
if (
|
|
4825
|
-
// Hash doesn't contain key/value pairs
|
|
4535
|
+
static isAccessTokenEntity(entity) {
|
|
4536
|
+
if (!entity) {
|
|
4826
4537
|
return false;
|
|
4827
4538
|
}
|
|
4828
|
-
|
|
4829
|
-
|
|
4830
|
-
|
|
4831
|
-
|
|
4832
|
-
|
|
4539
|
+
return (entity.hasOwnProperty("homeAccountId") &&
|
|
4540
|
+
entity.hasOwnProperty("environment") &&
|
|
4541
|
+
entity.hasOwnProperty("credentialType") &&
|
|
4542
|
+
entity.hasOwnProperty("realm") &&
|
|
4543
|
+
entity.hasOwnProperty("clientId") &&
|
|
4544
|
+
entity.hasOwnProperty("secret") &&
|
|
4545
|
+
entity.hasOwnProperty("target") &&
|
|
4546
|
+
(entity["credentialType"] === CredentialType.ACCESS_TOKEN ||
|
|
4547
|
+
entity["credentialType"] ===
|
|
4548
|
+
CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME));
|
|
4833
4549
|
}
|
|
4834
4550
|
}
|
|
4835
4551
|
|
|
@@ -4838,227 +4554,504 @@ class UrlString {
|
|
|
4838
4554
|
* Licensed under the MIT License.
|
|
4839
4555
|
*/
|
|
4840
4556
|
/**
|
|
4841
|
-
*
|
|
4557
|
+
* REFRESH_TOKEN Cache
|
|
4842
4558
|
*
|
|
4843
|
-
*
|
|
4844
|
-
*
|
|
4559
|
+
* Key:Value Schema:
|
|
4560
|
+
*
|
|
4561
|
+
* Key Example: uid.utid-login.microsoftonline.com-refreshtoken-clientId--
|
|
4562
|
+
*
|
|
4563
|
+
* Value:
|
|
4564
|
+
* {
|
|
4565
|
+
* homeAccountId: home account identifier for the auth scheme,
|
|
4566
|
+
* environment: entity that issued the token, represented as a full host
|
|
4567
|
+
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
|
4568
|
+
* clientId: client ID of the application
|
|
4569
|
+
* secret: Actual credential as a string
|
|
4570
|
+
* familyId: Family ID identifier, '1' represents Microsoft Family
|
|
4571
|
+
* realm: Full tenant or organizational identifier that the account belongs to
|
|
4572
|
+
* target: Permissions that are included in the token, or for refresh tokens, the resource identifier.
|
|
4573
|
+
* }
|
|
4845
4574
|
*/
|
|
4846
|
-
|
|
4847
|
-
/**
|
|
4848
|
-
* acquireTokenByCode API (msal-browser and msal-node).
|
|
4849
|
-
* Used to acquire tokens by trading an authorization code against the token endpoint.
|
|
4850
|
-
*/
|
|
4851
|
-
AcquireTokenByCode: "acquireTokenByCode",
|
|
4852
|
-
/**
|
|
4853
|
-
* acquireTokenByRefreshToken API (msal-browser and msal-node).
|
|
4854
|
-
* Used to renew an access token using a refresh token against the token endpoint.
|
|
4855
|
-
*/
|
|
4856
|
-
AcquireTokenByRefreshToken: "acquireTokenByRefreshToken",
|
|
4857
|
-
/**
|
|
4858
|
-
* acquireTokenSilent API (msal-browser and msal-node).
|
|
4859
|
-
* Used to silently acquire a new access token (from the cache or the network).
|
|
4860
|
-
*/
|
|
4861
|
-
AcquireTokenSilent: "acquireTokenSilent",
|
|
4862
|
-
/**
|
|
4863
|
-
* acquireTokenSilentAsync (msal-browser).
|
|
4864
|
-
* Internal API for acquireTokenSilent.
|
|
4865
|
-
*/
|
|
4866
|
-
AcquireTokenSilentAsync: "acquireTokenSilentAsync",
|
|
4867
|
-
/**
|
|
4868
|
-
* acquireTokenPopup (msal-browser).
|
|
4869
|
-
* Used to acquire a new access token interactively through pop ups
|
|
4870
|
-
*/
|
|
4871
|
-
AcquireTokenPopup: "acquireTokenPopup",
|
|
4872
|
-
/**
|
|
4873
|
-
* getPublicKeyThumbprint API in CryptoOpts class (msal-browser).
|
|
4874
|
-
* Used to generate a public/private keypair and generate a public key thumbprint for pop requests.
|
|
4875
|
-
*/
|
|
4876
|
-
CryptoOptsGetPublicKeyThumbprint: "cryptoOptsGetPublicKeyThumbprint",
|
|
4877
|
-
/**
|
|
4878
|
-
* signJwt API in CryptoOpts class (msal-browser).
|
|
4879
|
-
* Used to signed a pop token.
|
|
4880
|
-
*/
|
|
4881
|
-
CryptoOptsSignJwt: "cryptoOptsSignJwt",
|
|
4882
|
-
/**
|
|
4883
|
-
* acquireToken API in the SilentCacheClient class (msal-browser).
|
|
4884
|
-
* Used to read access tokens from the cache.
|
|
4885
|
-
*/
|
|
4886
|
-
SilentCacheClientAcquireToken: "silentCacheClientAcquireToken",
|
|
4887
|
-
/**
|
|
4888
|
-
* acquireToken API in the SilentIframeClient class (msal-browser).
|
|
4889
|
-
* Used to acquire a new set of tokens from the authorize endpoint in a hidden iframe.
|
|
4890
|
-
*/
|
|
4891
|
-
SilentIframeClientAcquireToken: "silentIframeClientAcquireToken",
|
|
4892
|
-
/**
|
|
4893
|
-
* acquireToken API in SilentRereshClient (msal-browser).
|
|
4894
|
-
* Used to acquire a new set of tokens from the token endpoint using a refresh token.
|
|
4895
|
-
*/
|
|
4896
|
-
SilentRefreshClientAcquireToken: "silentRefreshClientAcquireToken",
|
|
4897
|
-
/**
|
|
4898
|
-
* ssoSilent API (msal-browser).
|
|
4899
|
-
* Used to silently acquire an authorization code and set of tokens using a hidden iframe.
|
|
4900
|
-
*/
|
|
4901
|
-
SsoSilent: "ssoSilent",
|
|
4902
|
-
/**
|
|
4903
|
-
* getDiscoveredAuthority API in StandardInteractionClient class (msal-browser).
|
|
4904
|
-
* Used to load authority metadata for a request.
|
|
4905
|
-
*/
|
|
4906
|
-
StandardInteractionClientGetDiscoveredAuthority: "standardInteractionClientGetDiscoveredAuthority",
|
|
4907
|
-
/**
|
|
4908
|
-
* acquireToken APIs in msal-browser.
|
|
4909
|
-
* Used to make an /authorize endpoint call with native brokering enabled.
|
|
4910
|
-
*/
|
|
4911
|
-
FetchAccountIdWithNativeBroker: "fetchAccountIdWithNativeBroker",
|
|
4912
|
-
/**
|
|
4913
|
-
* acquireToken API in NativeInteractionClient class (msal-browser).
|
|
4914
|
-
* Used to acquire a token from Native component when native brokering is enabled.
|
|
4915
|
-
*/
|
|
4916
|
-
NativeInteractionClientAcquireToken: "nativeInteractionClientAcquireToken",
|
|
4917
|
-
/**
|
|
4918
|
-
* Time spent creating default headers for requests to token endpoint
|
|
4919
|
-
*/
|
|
4920
|
-
BaseClientCreateTokenRequestHeaders: "baseClientCreateTokenRequestHeaders",
|
|
4575
|
+
class RefreshTokenEntity extends CredentialEntity {
|
|
4921
4576
|
/**
|
|
4922
|
-
*
|
|
4577
|
+
* Create RefreshTokenEntity
|
|
4578
|
+
* @param homeAccountId
|
|
4579
|
+
* @param authenticationResult
|
|
4580
|
+
* @param clientId
|
|
4581
|
+
* @param authority
|
|
4923
4582
|
*/
|
|
4924
|
-
|
|
4583
|
+
static createRefreshTokenEntity(homeAccountId, environment, refreshToken, clientId, familyId, userAssertionHash) {
|
|
4584
|
+
const rtEntity = new RefreshTokenEntity();
|
|
4585
|
+
rtEntity.clientId = clientId;
|
|
4586
|
+
rtEntity.credentialType = CredentialType.REFRESH_TOKEN;
|
|
4587
|
+
rtEntity.environment = environment;
|
|
4588
|
+
rtEntity.homeAccountId = homeAccountId;
|
|
4589
|
+
rtEntity.secret = refreshToken;
|
|
4590
|
+
rtEntity.userAssertionHash = userAssertionHash;
|
|
4591
|
+
if (familyId)
|
|
4592
|
+
rtEntity.familyId = familyId;
|
|
4593
|
+
return rtEntity;
|
|
4594
|
+
}
|
|
4925
4595
|
/**
|
|
4926
|
-
*
|
|
4596
|
+
* Validates an entity: checks for all expected params
|
|
4597
|
+
* @param entity
|
|
4927
4598
|
*/
|
|
4928
|
-
|
|
4599
|
+
static isRefreshTokenEntity(entity) {
|
|
4600
|
+
if (!entity) {
|
|
4601
|
+
return false;
|
|
4602
|
+
}
|
|
4603
|
+
return (entity.hasOwnProperty("homeAccountId") &&
|
|
4604
|
+
entity.hasOwnProperty("environment") &&
|
|
4605
|
+
entity.hasOwnProperty("credentialType") &&
|
|
4606
|
+
entity.hasOwnProperty("clientId") &&
|
|
4607
|
+
entity.hasOwnProperty("secret") &&
|
|
4608
|
+
entity["credentialType"] === CredentialType.REFRESH_TOKEN);
|
|
4609
|
+
}
|
|
4610
|
+
}
|
|
4611
|
+
|
|
4612
|
+
/*
|
|
4613
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4614
|
+
* Licensed under the MIT License.
|
|
4615
|
+
*/
|
|
4616
|
+
/**
|
|
4617
|
+
* InteractionRequiredServerErrorMessage contains string constants used by error codes and messages returned by the server indicating interaction is required
|
|
4618
|
+
*/
|
|
4619
|
+
const InteractionRequiredServerErrorMessage = [
|
|
4620
|
+
"interaction_required",
|
|
4621
|
+
"consent_required",
|
|
4622
|
+
"login_required",
|
|
4623
|
+
];
|
|
4624
|
+
const InteractionRequiredAuthSubErrorMessage = [
|
|
4625
|
+
"message_only",
|
|
4626
|
+
"additional_action",
|
|
4627
|
+
"basic_action",
|
|
4628
|
+
"user_password_expired",
|
|
4629
|
+
"consent_required",
|
|
4630
|
+
];
|
|
4631
|
+
/**
|
|
4632
|
+
* Interaction required errors defined by the SDK
|
|
4633
|
+
*/
|
|
4634
|
+
const InteractionRequiredAuthErrorMessage = {
|
|
4635
|
+
noTokensFoundError: {
|
|
4636
|
+
code: "no_tokens_found",
|
|
4637
|
+
desc: "No refresh token found in the cache. Please sign-in.",
|
|
4638
|
+
},
|
|
4639
|
+
native_account_unavailable: {
|
|
4640
|
+
code: "native_account_unavailable",
|
|
4641
|
+
desc: "The requested account is not available in the native broker. It may have been deleted or logged out. Please sign-in again using an interactive API.",
|
|
4642
|
+
},
|
|
4643
|
+
};
|
|
4644
|
+
/**
|
|
4645
|
+
* Error thrown when user interaction is required.
|
|
4646
|
+
*/
|
|
4647
|
+
class InteractionRequiredAuthError extends AuthError {
|
|
4648
|
+
constructor(errorCode, errorMessage, subError, timestamp, traceId, correlationId, claims) {
|
|
4649
|
+
super(errorCode, errorMessage, subError);
|
|
4650
|
+
Object.setPrototypeOf(this, InteractionRequiredAuthError.prototype);
|
|
4651
|
+
this.timestamp = timestamp || Constants.EMPTY_STRING;
|
|
4652
|
+
this.traceId = traceId || Constants.EMPTY_STRING;
|
|
4653
|
+
this.correlationId = correlationId || Constants.EMPTY_STRING;
|
|
4654
|
+
this.claims = claims || Constants.EMPTY_STRING;
|
|
4655
|
+
this.name = "InteractionRequiredAuthError";
|
|
4656
|
+
}
|
|
4929
4657
|
/**
|
|
4930
|
-
*
|
|
4658
|
+
* Helper function used to determine if an error thrown by the server requires interaction to resolve
|
|
4659
|
+
* @param errorCode
|
|
4660
|
+
* @param errorString
|
|
4661
|
+
* @param subError
|
|
4931
4662
|
*/
|
|
4932
|
-
|
|
4663
|
+
static isInteractionRequiredError(errorCode, errorString, subError) {
|
|
4664
|
+
const isInteractionRequiredErrorCode = !!errorCode &&
|
|
4665
|
+
InteractionRequiredServerErrorMessage.indexOf(errorCode) > -1;
|
|
4666
|
+
const isInteractionRequiredSubError = !!subError &&
|
|
4667
|
+
InteractionRequiredAuthSubErrorMessage.indexOf(subError) > -1;
|
|
4668
|
+
const isInteractionRequiredErrorDesc = !!errorString &&
|
|
4669
|
+
InteractionRequiredServerErrorMessage.some((irErrorCode) => {
|
|
4670
|
+
return errorString.indexOf(irErrorCode) > -1;
|
|
4671
|
+
});
|
|
4672
|
+
return (isInteractionRequiredErrorCode ||
|
|
4673
|
+
isInteractionRequiredErrorDesc ||
|
|
4674
|
+
isInteractionRequiredSubError);
|
|
4675
|
+
}
|
|
4933
4676
|
/**
|
|
4934
|
-
*
|
|
4677
|
+
* Creates an error thrown when the authorization code required for a token request is null or empty.
|
|
4935
4678
|
*/
|
|
4936
|
-
|
|
4679
|
+
static createNoTokensFoundError() {
|
|
4680
|
+
return new InteractionRequiredAuthError(InteractionRequiredAuthErrorMessage.noTokensFoundError.code, InteractionRequiredAuthErrorMessage.noTokensFoundError.desc);
|
|
4681
|
+
}
|
|
4937
4682
|
/**
|
|
4938
|
-
*
|
|
4683
|
+
* Creates an error thrown when the native broker returns ACCOUNT_UNAVAILABLE status, indicating that the account was removed and interactive sign-in is required
|
|
4684
|
+
* @returns
|
|
4939
4685
|
*/
|
|
4940
|
-
|
|
4686
|
+
static createNativeAccountUnavailableError() {
|
|
4687
|
+
return new InteractionRequiredAuthError(InteractionRequiredAuthErrorMessage.native_account_unavailable.code, InteractionRequiredAuthErrorMessage.native_account_unavailable.desc);
|
|
4688
|
+
}
|
|
4689
|
+
}
|
|
4690
|
+
|
|
4691
|
+
/*
|
|
4692
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4693
|
+
* Licensed under the MIT License.
|
|
4694
|
+
*/
|
|
4695
|
+
/** @internal */
|
|
4696
|
+
class CacheRecord {
|
|
4697
|
+
constructor(accountEntity, idTokenEntity, accessTokenEntity, refreshTokenEntity, appMetadataEntity) {
|
|
4698
|
+
this.account = accountEntity || null;
|
|
4699
|
+
this.idToken = idTokenEntity || null;
|
|
4700
|
+
this.accessToken = accessTokenEntity || null;
|
|
4701
|
+
this.refreshToken = refreshTokenEntity || null;
|
|
4702
|
+
this.appMetadata = appMetadataEntity || null;
|
|
4703
|
+
}
|
|
4704
|
+
}
|
|
4705
|
+
|
|
4706
|
+
/*
|
|
4707
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4708
|
+
* Licensed under the MIT License.
|
|
4709
|
+
*/
|
|
4710
|
+
/**
|
|
4711
|
+
* Class which provides helpers for OAuth 2.0 protocol specific values
|
|
4712
|
+
*/
|
|
4713
|
+
class ProtocolUtils {
|
|
4941
4714
|
/**
|
|
4942
|
-
*
|
|
4715
|
+
* Appends user state with random guid, or returns random guid.
|
|
4716
|
+
* @param userState
|
|
4717
|
+
* @param randomGuid
|
|
4943
4718
|
*/
|
|
4944
|
-
|
|
4719
|
+
static setRequestState(cryptoObj, userState, meta) {
|
|
4720
|
+
const libraryState = ProtocolUtils.generateLibraryState(cryptoObj, meta);
|
|
4721
|
+
return userState
|
|
4722
|
+
? `${libraryState}${Constants.RESOURCE_DELIM}${userState}`
|
|
4723
|
+
: libraryState;
|
|
4724
|
+
}
|
|
4945
4725
|
/**
|
|
4946
|
-
*
|
|
4726
|
+
* Generates the state value used by the common library.
|
|
4727
|
+
* @param randomGuid
|
|
4728
|
+
* @param cryptoObj
|
|
4947
4729
|
*/
|
|
4948
|
-
|
|
4730
|
+
static generateLibraryState(cryptoObj, meta) {
|
|
4731
|
+
if (!cryptoObj) {
|
|
4732
|
+
throw ClientAuthError.createNoCryptoObjectError("generateLibraryState");
|
|
4733
|
+
}
|
|
4734
|
+
// Create a state object containing a unique id and the timestamp of the request creation
|
|
4735
|
+
const stateObj = {
|
|
4736
|
+
id: cryptoObj.createNewGuid(),
|
|
4737
|
+
};
|
|
4738
|
+
if (meta) {
|
|
4739
|
+
stateObj.meta = meta;
|
|
4740
|
+
}
|
|
4741
|
+
const stateString = JSON.stringify(stateObj);
|
|
4742
|
+
return cryptoObj.base64Encode(stateString);
|
|
4743
|
+
}
|
|
4949
4744
|
/**
|
|
4950
|
-
*
|
|
4745
|
+
* Parses the state into the RequestStateObject, which contains the LibraryState info and the state passed by the user.
|
|
4746
|
+
* @param state
|
|
4747
|
+
* @param cryptoObj
|
|
4951
4748
|
*/
|
|
4952
|
-
|
|
4749
|
+
static parseRequestState(cryptoObj, state) {
|
|
4750
|
+
if (!cryptoObj) {
|
|
4751
|
+
throw ClientAuthError.createNoCryptoObjectError("parseRequestState");
|
|
4752
|
+
}
|
|
4753
|
+
if (!state) {
|
|
4754
|
+
throw ClientAuthError.createInvalidStateError(state, "Null, undefined or empty state");
|
|
4755
|
+
}
|
|
4756
|
+
try {
|
|
4757
|
+
// Split the state between library state and user passed state and decode them separately
|
|
4758
|
+
const splitState = state.split(Constants.RESOURCE_DELIM);
|
|
4759
|
+
const libraryState = splitState[0];
|
|
4760
|
+
const userState = splitState.length > 1
|
|
4761
|
+
? splitState.slice(1).join(Constants.RESOURCE_DELIM)
|
|
4762
|
+
: Constants.EMPTY_STRING;
|
|
4763
|
+
const libraryStateString = cryptoObj.base64Decode(libraryState);
|
|
4764
|
+
const libraryStateObj = JSON.parse(libraryStateString);
|
|
4765
|
+
return {
|
|
4766
|
+
userRequestState: userState || Constants.EMPTY_STRING,
|
|
4767
|
+
libraryState: libraryStateObj,
|
|
4768
|
+
};
|
|
4769
|
+
}
|
|
4770
|
+
catch (e) {
|
|
4771
|
+
throw ClientAuthError.createInvalidStateError(state, e);
|
|
4772
|
+
}
|
|
4773
|
+
}
|
|
4774
|
+
}
|
|
4775
|
+
|
|
4776
|
+
/*
|
|
4777
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4778
|
+
* Licensed under the MIT License.
|
|
4779
|
+
*/
|
|
4780
|
+
/**
|
|
4781
|
+
* Url object class which can perform various transformations on url strings.
|
|
4782
|
+
*/
|
|
4783
|
+
class UrlString {
|
|
4784
|
+
get urlString() {
|
|
4785
|
+
return this._urlString;
|
|
4786
|
+
}
|
|
4787
|
+
constructor(url) {
|
|
4788
|
+
this._urlString = url;
|
|
4789
|
+
if (!this._urlString) {
|
|
4790
|
+
// Throws error if url is empty
|
|
4791
|
+
throw ClientConfigurationError.createUrlEmptyError();
|
|
4792
|
+
}
|
|
4793
|
+
if (!this.getHash()) {
|
|
4794
|
+
this._urlString = UrlString.canonicalizeUri(url);
|
|
4795
|
+
}
|
|
4796
|
+
}
|
|
4953
4797
|
/**
|
|
4954
|
-
*
|
|
4955
|
-
*
|
|
4798
|
+
* Ensure urls are lower case and end with a / character.
|
|
4799
|
+
* @param url
|
|
4956
4800
|
*/
|
|
4957
|
-
|
|
4801
|
+
static canonicalizeUri(url) {
|
|
4802
|
+
if (url) {
|
|
4803
|
+
let lowerCaseUrl = url.toLowerCase();
|
|
4804
|
+
if (StringUtils.endsWith(lowerCaseUrl, "?")) {
|
|
4805
|
+
lowerCaseUrl = lowerCaseUrl.slice(0, -1);
|
|
4806
|
+
}
|
|
4807
|
+
else if (StringUtils.endsWith(lowerCaseUrl, "?/")) {
|
|
4808
|
+
lowerCaseUrl = lowerCaseUrl.slice(0, -2);
|
|
4809
|
+
}
|
|
4810
|
+
if (!StringUtils.endsWith(lowerCaseUrl, "/")) {
|
|
4811
|
+
lowerCaseUrl += "/";
|
|
4812
|
+
}
|
|
4813
|
+
return lowerCaseUrl;
|
|
4814
|
+
}
|
|
4815
|
+
return url;
|
|
4816
|
+
}
|
|
4958
4817
|
/**
|
|
4959
|
-
*
|
|
4960
|
-
* Internal API for acquiring token by silent Iframe
|
|
4818
|
+
* Throws if urlString passed is not a valid authority URI string.
|
|
4961
4819
|
*/
|
|
4962
|
-
|
|
4820
|
+
validateAsUri() {
|
|
4821
|
+
// Attempts to parse url for uri components
|
|
4822
|
+
let components;
|
|
4823
|
+
try {
|
|
4824
|
+
components = this.getUrlComponents();
|
|
4825
|
+
}
|
|
4826
|
+
catch (e) {
|
|
4827
|
+
throw ClientConfigurationError.createUrlParseError(e);
|
|
4828
|
+
}
|
|
4829
|
+
// Throw error if URI or path segments are not parseable.
|
|
4830
|
+
if (!components.HostNameAndPort || !components.PathSegments) {
|
|
4831
|
+
throw ClientConfigurationError.createUrlParseError(`Given url string: ${this.urlString}`);
|
|
4832
|
+
}
|
|
4833
|
+
// Throw error if uri is insecure.
|
|
4834
|
+
if (!components.Protocol ||
|
|
4835
|
+
components.Protocol.toLowerCase() !== "https:") {
|
|
4836
|
+
throw ClientConfigurationError.createInsecureAuthorityUriError(this.urlString);
|
|
4837
|
+
}
|
|
4838
|
+
}
|
|
4963
4839
|
/**
|
|
4964
|
-
*
|
|
4840
|
+
* Given a url and a query string return the url with provided query string appended
|
|
4841
|
+
* @param url
|
|
4842
|
+
* @param queryString
|
|
4965
4843
|
*/
|
|
4966
|
-
|
|
4844
|
+
static appendQueryString(url, queryString) {
|
|
4845
|
+
if (!queryString) {
|
|
4846
|
+
return url;
|
|
4847
|
+
}
|
|
4848
|
+
return url.indexOf("?") < 0
|
|
4849
|
+
? `${url}?${queryString}`
|
|
4850
|
+
: `${url}&${queryString}`;
|
|
4851
|
+
}
|
|
4967
4852
|
/**
|
|
4968
|
-
*
|
|
4853
|
+
* Returns a url with the hash removed
|
|
4854
|
+
* @param url
|
|
4969
4855
|
*/
|
|
4970
|
-
|
|
4971
|
-
|
|
4856
|
+
static removeHashFromUrl(url) {
|
|
4857
|
+
return UrlString.canonicalizeUri(url.split("#")[0]);
|
|
4858
|
+
}
|
|
4972
4859
|
/**
|
|
4973
|
-
*
|
|
4860
|
+
* Given a url like https://a:b/common/d?e=f#g, and a tenantId, returns https://a:b/tenantId/d
|
|
4861
|
+
* @param href The url
|
|
4862
|
+
* @param tenantId The tenant id to replace
|
|
4974
4863
|
*/
|
|
4975
|
-
|
|
4864
|
+
replaceTenantPath(tenantId) {
|
|
4865
|
+
const urlObject = this.getUrlComponents();
|
|
4866
|
+
const pathArray = urlObject.PathSegments;
|
|
4867
|
+
if (tenantId &&
|
|
4868
|
+
pathArray.length !== 0 &&
|
|
4869
|
+
(pathArray[0] === AADAuthorityConstants.COMMON ||
|
|
4870
|
+
pathArray[0] === AADAuthorityConstants.ORGANIZATIONS)) {
|
|
4871
|
+
pathArray[0] = tenantId;
|
|
4872
|
+
}
|
|
4873
|
+
return UrlString.constructAuthorityUriFromObject(urlObject);
|
|
4874
|
+
}
|
|
4976
4875
|
/**
|
|
4977
|
-
*
|
|
4876
|
+
* Returns the anchor part(#) of the URL
|
|
4978
4877
|
*/
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4878
|
+
getHash() {
|
|
4879
|
+
return UrlString.parseHash(this.urlString);
|
|
4880
|
+
}
|
|
4982
4881
|
/**
|
|
4983
|
-
*
|
|
4882
|
+
* Parses out the components from a url string.
|
|
4883
|
+
* @returns An object with the various components. Please cache this value insted of calling this multiple times on the same url.
|
|
4984
4884
|
*/
|
|
4985
|
-
|
|
4986
|
-
|
|
4987
|
-
|
|
4988
|
-
|
|
4885
|
+
getUrlComponents() {
|
|
4886
|
+
// https://gist.github.com/curtisz/11139b2cfcaef4a261e0
|
|
4887
|
+
const regEx = RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
|
|
4888
|
+
// If url string does not match regEx, we throw an error
|
|
4889
|
+
const match = this.urlString.match(regEx);
|
|
4890
|
+
if (!match) {
|
|
4891
|
+
throw ClientConfigurationError.createUrlParseError(`Given url string: ${this.urlString}`);
|
|
4892
|
+
}
|
|
4893
|
+
// Url component object
|
|
4894
|
+
const urlComponents = {
|
|
4895
|
+
Protocol: match[1],
|
|
4896
|
+
HostNameAndPort: match[4],
|
|
4897
|
+
AbsolutePath: match[5],
|
|
4898
|
+
QueryString: match[7],
|
|
4899
|
+
};
|
|
4900
|
+
let pathSegments = urlComponents.AbsolutePath.split("/");
|
|
4901
|
+
pathSegments = pathSegments.filter((val) => val && val.length > 0); // remove empty elements
|
|
4902
|
+
urlComponents.PathSegments = pathSegments;
|
|
4903
|
+
if (urlComponents.QueryString &&
|
|
4904
|
+
urlComponents.QueryString.endsWith("/")) {
|
|
4905
|
+
urlComponents.QueryString = urlComponents.QueryString.substring(0, urlComponents.QueryString.length - 1);
|
|
4906
|
+
}
|
|
4907
|
+
return urlComponents;
|
|
4908
|
+
}
|
|
4909
|
+
static getDomainFromUrl(url) {
|
|
4910
|
+
const regEx = RegExp("^([^:/?#]+://)?([^/?#]*)");
|
|
4911
|
+
const match = url.match(regEx);
|
|
4912
|
+
if (!match) {
|
|
4913
|
+
throw ClientConfigurationError.createUrlParseError(`Given url string: ${url}`);
|
|
4914
|
+
}
|
|
4915
|
+
return match[2];
|
|
4916
|
+
}
|
|
4917
|
+
static getAbsoluteUrl(relativeUrl, baseUrl) {
|
|
4918
|
+
if (relativeUrl[0] === Constants.FORWARD_SLASH) {
|
|
4919
|
+
const url = new UrlString(baseUrl);
|
|
4920
|
+
const baseComponents = url.getUrlComponents();
|
|
4921
|
+
return (baseComponents.Protocol +
|
|
4922
|
+
"//" +
|
|
4923
|
+
baseComponents.HostNameAndPort +
|
|
4924
|
+
relativeUrl);
|
|
4925
|
+
}
|
|
4926
|
+
return relativeUrl;
|
|
4927
|
+
}
|
|
4989
4928
|
/**
|
|
4990
|
-
*
|
|
4929
|
+
* Parses hash string from given string. Returns empty string if no hash symbol is found.
|
|
4930
|
+
* @param hashString
|
|
4991
4931
|
*/
|
|
4992
|
-
|
|
4932
|
+
static parseHash(hashString) {
|
|
4933
|
+
const hashIndex1 = hashString.indexOf("#");
|
|
4934
|
+
const hashIndex2 = hashString.indexOf("#/");
|
|
4935
|
+
if (hashIndex2 > -1) {
|
|
4936
|
+
return hashString.substring(hashIndex2 + 2);
|
|
4937
|
+
}
|
|
4938
|
+
else if (hashIndex1 > -1) {
|
|
4939
|
+
return hashString.substring(hashIndex1 + 1);
|
|
4940
|
+
}
|
|
4941
|
+
return Constants.EMPTY_STRING;
|
|
4942
|
+
}
|
|
4993
4943
|
/**
|
|
4994
|
-
*
|
|
4944
|
+
* Parses query string from given string. Returns empty string if no query symbol is found.
|
|
4945
|
+
* @param queryString
|
|
4995
4946
|
*/
|
|
4996
|
-
|
|
4997
|
-
|
|
4998
|
-
|
|
4947
|
+
static parseQueryString(queryString) {
|
|
4948
|
+
const queryIndex1 = queryString.indexOf("?");
|
|
4949
|
+
const queryIndex2 = queryString.indexOf("/?");
|
|
4950
|
+
if (queryIndex2 > -1) {
|
|
4951
|
+
return queryString.substring(queryIndex2 + 2);
|
|
4952
|
+
}
|
|
4953
|
+
else if (queryIndex1 > -1) {
|
|
4954
|
+
return queryString.substring(queryIndex1 + 1);
|
|
4955
|
+
}
|
|
4956
|
+
return Constants.EMPTY_STRING;
|
|
4957
|
+
}
|
|
4999
4958
|
/**
|
|
5000
|
-
*
|
|
4959
|
+
* Parses query server response string from given string.
|
|
4960
|
+
* Extract hash between '?code=' and '#' if trailing '# is present.
|
|
4961
|
+
* Returns empty string if no query symbol is found.
|
|
4962
|
+
* @param queryString
|
|
5001
4963
|
*/
|
|
5002
|
-
|
|
5003
|
-
|
|
5004
|
-
|
|
5005
|
-
|
|
4964
|
+
static parseQueryServerResponse(queryString) {
|
|
4965
|
+
const queryIndex1 = queryString.indexOf("?code");
|
|
4966
|
+
const queryIndex2 = queryString.indexOf("/?code");
|
|
4967
|
+
const hashIndex = queryString.indexOf("#");
|
|
4968
|
+
if (queryIndex2 > -1 && hashIndex > -1) {
|
|
4969
|
+
return queryString.substring(queryIndex2 + 2, hashIndex);
|
|
4970
|
+
}
|
|
4971
|
+
else if (queryIndex2 > -1) {
|
|
4972
|
+
return queryString.substring(queryIndex2 + 2);
|
|
4973
|
+
}
|
|
4974
|
+
else if (queryIndex1 > -1 && hashIndex > -1) {
|
|
4975
|
+
return queryString.substring(queryIndex1 + 1, hashIndex);
|
|
4976
|
+
}
|
|
4977
|
+
else if (queryIndex1 > -1) {
|
|
4978
|
+
return queryString.substring(queryIndex1 + 1);
|
|
4979
|
+
}
|
|
4980
|
+
return Constants.EMPTY_STRING;
|
|
4981
|
+
}
|
|
4982
|
+
static constructAuthorityUriFromObject(urlObject) {
|
|
4983
|
+
return new UrlString(urlObject.Protocol +
|
|
4984
|
+
"//" +
|
|
4985
|
+
urlObject.HostNameAndPort +
|
|
4986
|
+
"/" +
|
|
4987
|
+
urlObject.PathSegments.join("/"));
|
|
4988
|
+
}
|
|
5006
4989
|
/**
|
|
5007
|
-
*
|
|
4990
|
+
* Returns URL hash as server auth code response object.
|
|
5008
4991
|
*/
|
|
5009
|
-
|
|
5010
|
-
|
|
4992
|
+
static getDeserializedHash(hash) {
|
|
4993
|
+
// Check if given hash is empty
|
|
4994
|
+
if (!hash) {
|
|
4995
|
+
return {};
|
|
4996
|
+
}
|
|
4997
|
+
// Strip the # symbol if present
|
|
4998
|
+
const parsedHash = UrlString.parseHash(hash);
|
|
4999
|
+
// If # symbol was not present, above will return empty string, so give original hash value
|
|
5000
|
+
const deserializedHash = StringUtils.queryStringToObject(parsedHash || hash);
|
|
5001
|
+
// Check if deserialization didn't work
|
|
5002
|
+
if (!deserializedHash) {
|
|
5003
|
+
throw ClientAuthError.createHashNotDeserializedError(JSON.stringify(deserializedHash));
|
|
5004
|
+
}
|
|
5005
|
+
return deserializedHash;
|
|
5006
|
+
}
|
|
5011
5007
|
/**
|
|
5012
|
-
*
|
|
5008
|
+
* Returns URL query string as server auth code response object.
|
|
5013
5009
|
*/
|
|
5014
|
-
|
|
5010
|
+
static getDeserializedQueryString(query) {
|
|
5011
|
+
// Check if given query is empty
|
|
5012
|
+
if (!query) {
|
|
5013
|
+
return {};
|
|
5014
|
+
}
|
|
5015
|
+
// Strip the ? symbol if present
|
|
5016
|
+
const parsedQueryString = UrlString.parseQueryString(query);
|
|
5017
|
+
// If ? symbol was not present, above will return empty string, so give original query value
|
|
5018
|
+
const deserializedQueryString = StringUtils.queryStringToObject(parsedQueryString || query);
|
|
5019
|
+
// Check if deserialization didn't work
|
|
5020
|
+
if (!deserializedQueryString) {
|
|
5021
|
+
throw ClientAuthError.createHashNotDeserializedError(JSON.stringify(deserializedQueryString));
|
|
5022
|
+
}
|
|
5023
|
+
return deserializedQueryString;
|
|
5024
|
+
}
|
|
5015
5025
|
/**
|
|
5016
|
-
*
|
|
5026
|
+
* Returns either deserialized query string or deserialized hash, depending on the serverResponseType
|
|
5027
|
+
* as a server auth code response object.
|
|
5017
5028
|
*/
|
|
5018
|
-
|
|
5019
|
-
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5029
|
+
static getDeserializedCodeResponse(serverResponseType, hashFragment) {
|
|
5030
|
+
const hashUrlString = new UrlString(hashFragment);
|
|
5031
|
+
let serverParams;
|
|
5032
|
+
if (serverResponseType === ServerResponseType.QUERY) {
|
|
5033
|
+
serverParams = UrlString.getDeserializedQueryString(hashFragment);
|
|
5034
|
+
}
|
|
5035
|
+
else {
|
|
5036
|
+
serverParams = UrlString.getDeserializedHash(hashUrlString.getHash());
|
|
5037
|
+
}
|
|
5038
|
+
return serverParams;
|
|
5039
|
+
}
|
|
5025
5040
|
/**
|
|
5026
|
-
*
|
|
5041
|
+
* Check if the hash of the URL string contains known properties
|
|
5027
5042
|
*/
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
}
|
|
5040
|
-
/**
|
|
5041
|
-
* State of the performance event.
|
|
5042
|
-
*
|
|
5043
|
-
* @export
|
|
5044
|
-
* @enum {number}
|
|
5045
|
-
*/
|
|
5046
|
-
const PerformanceEventStatus = {
|
|
5047
|
-
NotStarted: 0,
|
|
5048
|
-
InProgress: 1,
|
|
5049
|
-
Completed: 2,
|
|
5050
|
-
};
|
|
5051
|
-
const IntFields = new Set([
|
|
5052
|
-
"accessTokenSize",
|
|
5053
|
-
"durationMs",
|
|
5054
|
-
"idTokenSize",
|
|
5055
|
-
"matsSilentStatus",
|
|
5056
|
-
"matsHttpStatus",
|
|
5057
|
-
"refreshTokenSize",
|
|
5058
|
-
"queuedTimeMs",
|
|
5059
|
-
"startTimeMs",
|
|
5060
|
-
"status",
|
|
5061
|
-
]);
|
|
5043
|
+
static hashContainsKnownProperties(hash) {
|
|
5044
|
+
if (!hash || hash.indexOf("=") < 0) {
|
|
5045
|
+
// Hash doesn't contain key/value pairs
|
|
5046
|
+
return false;
|
|
5047
|
+
}
|
|
5048
|
+
const parameters = UrlString.getDeserializedHash(hash);
|
|
5049
|
+
return !!(parameters.code ||
|
|
5050
|
+
parameters.error_description ||
|
|
5051
|
+
parameters.error ||
|
|
5052
|
+
parameters.state);
|
|
5053
|
+
}
|
|
5054
|
+
}
|
|
5062
5055
|
|
|
5063
5056
|
/*
|
|
5064
5057
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -5300,17 +5293,37 @@ class ResponseHandler {
|
|
|
5300
5293
|
/**
|
|
5301
5294
|
* Function which validates server authorization token response.
|
|
5302
5295
|
* @param serverResponse
|
|
5296
|
+
* @param refreshAccessToken
|
|
5303
5297
|
*/
|
|
5304
|
-
validateTokenResponse(serverResponse) {
|
|
5298
|
+
validateTokenResponse(serverResponse, refreshAccessToken) {
|
|
5305
5299
|
// Check for error
|
|
5306
5300
|
if (serverResponse.error ||
|
|
5307
5301
|
serverResponse.error_description ||
|
|
5308
5302
|
serverResponse.suberror) {
|
|
5303
|
+
const errString = `${serverResponse.error_codes} - [${serverResponse.timestamp}]: ${serverResponse.error_description} - Correlation ID: ${serverResponse.correlation_id} - Trace ID: ${serverResponse.trace_id}`;
|
|
5304
|
+
const serverError = new ServerError(serverResponse.error, errString, serverResponse.suberror);
|
|
5305
|
+
// check if 500 error
|
|
5306
|
+
if (refreshAccessToken &&
|
|
5307
|
+
serverResponse.status &&
|
|
5308
|
+
serverResponse.status >= HttpStatus.SERVER_ERROR_RANGE_START &&
|
|
5309
|
+
serverResponse.status <= HttpStatus.SERVER_ERROR_RANGE_END) {
|
|
5310
|
+
this.logger.warning(`executeTokenRequest:validateTokenResponse - AAD is currently unavailable and the access token is unable to be refreshed.\n${serverError}`);
|
|
5311
|
+
// don't throw an exception, but alert the user via a log that the token was unable to be refreshed
|
|
5312
|
+
return;
|
|
5313
|
+
// check if 400 error
|
|
5314
|
+
}
|
|
5315
|
+
else if (refreshAccessToken &&
|
|
5316
|
+
serverResponse.status &&
|
|
5317
|
+
serverResponse.status >= HttpStatus.CLIENT_ERROR_RANGE_START &&
|
|
5318
|
+
serverResponse.status <= HttpStatus.CLIENT_ERROR_RANGE_END) {
|
|
5319
|
+
this.logger.warning(`executeTokenRequest:validateTokenResponse - AAD is currently available but is unable to refresh the access token.\n${serverError}`);
|
|
5320
|
+
// don't throw an exception, but alert the user via a log that the token was unable to be refreshed
|
|
5321
|
+
return;
|
|
5322
|
+
}
|
|
5309
5323
|
if (InteractionRequiredAuthError.isInteractionRequiredError(serverResponse.error, serverResponse.error_description, serverResponse.suberror)) {
|
|
5310
5324
|
throw new InteractionRequiredAuthError(serverResponse.error, serverResponse.error_description, serverResponse.suberror, serverResponse.timestamp || Constants.EMPTY_STRING, serverResponse.trace_id || Constants.EMPTY_STRING, serverResponse.correlation_id || Constants.EMPTY_STRING, serverResponse.claims || Constants.EMPTY_STRING);
|
|
5311
5325
|
}
|
|
5312
|
-
|
|
5313
|
-
throw new ServerError(serverResponse.error, errString, serverResponse.suberror);
|
|
5326
|
+
throw serverError;
|
|
5314
5327
|
}
|
|
5315
5328
|
}
|
|
5316
5329
|
/**
|
|
@@ -5321,27 +5334,26 @@ class ResponseHandler {
|
|
|
5321
5334
|
async handleServerTokenResponse(serverTokenResponse, authority, reqTimestamp, request, authCodePayload, userAssertionHash, handlingRefreshTokenResponse, forceCacheRefreshTokenResponse, serverRequestId) {
|
|
5322
5335
|
this.performanceClient?.addQueueMeasurement(PerformanceEvents.HandleServerTokenResponse, serverTokenResponse.correlation_id);
|
|
5323
5336
|
// create an idToken object (not entity)
|
|
5324
|
-
let
|
|
5337
|
+
let idTokenClaims;
|
|
5325
5338
|
if (serverTokenResponse.id_token) {
|
|
5326
|
-
|
|
5339
|
+
idTokenClaims = extractTokenClaims(serverTokenResponse.id_token || Constants.EMPTY_STRING, this.cryptoObj.base64Decode);
|
|
5327
5340
|
// token nonce check (TODO: Add a warning if no nonce is given?)
|
|
5328
|
-
if (authCodePayload &&
|
|
5329
|
-
|
|
5330
|
-
if (idTokenObj.claims.nonce !== authCodePayload.nonce) {
|
|
5341
|
+
if (authCodePayload && authCodePayload.nonce) {
|
|
5342
|
+
if (idTokenClaims.nonce !== authCodePayload.nonce) {
|
|
5331
5343
|
throw ClientAuthError.createNonceMismatchError();
|
|
5332
5344
|
}
|
|
5333
5345
|
}
|
|
5334
5346
|
// token max_age check
|
|
5335
5347
|
if (request.maxAge || request.maxAge === 0) {
|
|
5336
|
-
const authTime =
|
|
5348
|
+
const authTime = idTokenClaims.auth_time;
|
|
5337
5349
|
if (!authTime) {
|
|
5338
5350
|
throw ClientAuthError.createAuthTimeNotFoundError();
|
|
5339
5351
|
}
|
|
5340
|
-
|
|
5352
|
+
checkMaxAge(authTime, request.maxAge);
|
|
5341
5353
|
}
|
|
5342
5354
|
}
|
|
5343
5355
|
// generate homeAccountId
|
|
5344
|
-
this.homeAccountIdentifier = AccountEntity.generateHomeAccountId(serverTokenResponse.client_info || Constants.EMPTY_STRING, authority.authorityType, this.logger, this.cryptoObj,
|
|
5356
|
+
this.homeAccountIdentifier = AccountEntity.generateHomeAccountId(serverTokenResponse.client_info || Constants.EMPTY_STRING, authority.authorityType, this.logger, this.cryptoObj, idTokenClaims);
|
|
5345
5357
|
// save the response tokens
|
|
5346
5358
|
let requestStateObj;
|
|
5347
5359
|
if (!!authCodePayload && !!authCodePayload.state) {
|
|
@@ -5350,7 +5362,7 @@ class ResponseHandler {
|
|
|
5350
5362
|
// Add keyId from request to serverTokenResponse if defined
|
|
5351
5363
|
serverTokenResponse.key_id =
|
|
5352
5364
|
serverTokenResponse.key_id || request.sshKid || undefined;
|
|
5353
|
-
const cacheRecord = this.generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request,
|
|
5365
|
+
const cacheRecord = this.generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenClaims, userAssertionHash, authCodePayload);
|
|
5354
5366
|
let cacheContext;
|
|
5355
5367
|
try {
|
|
5356
5368
|
if (this.persistencePlugin && this.serializableCache) {
|
|
@@ -5371,7 +5383,7 @@ class ResponseHandler {
|
|
|
5371
5383
|
const account = this.cacheStorage.getAccount(key);
|
|
5372
5384
|
if (!account) {
|
|
5373
5385
|
this.logger.warning("Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache");
|
|
5374
|
-
return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request,
|
|
5386
|
+
return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenClaims, requestStateObj, undefined, serverRequestId);
|
|
5375
5387
|
}
|
|
5376
5388
|
}
|
|
5377
5389
|
await this.cacheStorage.saveCacheRecord(cacheRecord, request.storeInCache);
|
|
@@ -5384,7 +5396,7 @@ class ResponseHandler {
|
|
|
5384
5396
|
await this.persistencePlugin.afterCacheAccess(cacheContext);
|
|
5385
5397
|
}
|
|
5386
5398
|
}
|
|
5387
|
-
return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request,
|
|
5399
|
+
return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenClaims, requestStateObj, serverTokenResponse, serverRequestId);
|
|
5388
5400
|
}
|
|
5389
5401
|
/**
|
|
5390
5402
|
* Generates CacheRecord
|
|
@@ -5392,20 +5404,19 @@ class ResponseHandler {
|
|
|
5392
5404
|
* @param idTokenObj
|
|
5393
5405
|
* @param authority
|
|
5394
5406
|
*/
|
|
5395
|
-
generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request,
|
|
5407
|
+
generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenClaims, userAssertionHash, authCodePayload) {
|
|
5396
5408
|
const env = authority.getPreferredCache();
|
|
5397
|
-
if (
|
|
5409
|
+
if (!env) {
|
|
5398
5410
|
throw ClientAuthError.createInvalidCacheEnvironmentError();
|
|
5399
5411
|
}
|
|
5400
5412
|
// IdToken: non AAD scenarios can have empty realm
|
|
5401
5413
|
let cachedIdToken;
|
|
5402
5414
|
let cachedAccount;
|
|
5403
|
-
if (
|
|
5404
|
-
|
|
5405
|
-
cachedIdToken = IdTokenEntity.createIdTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.id_token || Constants.EMPTY_STRING, this.clientId, idTokenObj.claims.tid || Constants.EMPTY_STRING);
|
|
5415
|
+
if (serverTokenResponse.id_token && !!idTokenClaims) {
|
|
5416
|
+
cachedIdToken = IdTokenEntity.createIdTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.id_token, this.clientId, idTokenClaims.tid || "");
|
|
5406
5417
|
cachedAccount = AccountEntity.createAccount({
|
|
5407
5418
|
homeAccountId: this.homeAccountIdentifier,
|
|
5408
|
-
idTokenClaims:
|
|
5419
|
+
idTokenClaims: idTokenClaims,
|
|
5409
5420
|
clientInfo: serverTokenResponse.client_info,
|
|
5410
5421
|
cloudGraphHostName: authCodePayload?.cloud_graph_host_name,
|
|
5411
5422
|
msGraphHost: authCodePayload?.msgraph_host,
|
|
@@ -5413,7 +5424,7 @@ class ResponseHandler {
|
|
|
5413
5424
|
}
|
|
5414
5425
|
// AccessToken
|
|
5415
5426
|
let cachedAccessToken = null;
|
|
5416
|
-
if (
|
|
5427
|
+
if (serverTokenResponse.access_token) {
|
|
5417
5428
|
// If scopes not returned in server response, use request scopes
|
|
5418
5429
|
const responseScopes = serverTokenResponse.scope
|
|
5419
5430
|
? ScopeSet.fromString(serverTokenResponse.scope)
|
|
@@ -5437,18 +5448,16 @@ class ResponseHandler {
|
|
|
5437
5448
|
? reqTimestamp + refreshIn
|
|
5438
5449
|
: undefined;
|
|
5439
5450
|
// non AAD scenarios can have empty realm
|
|
5440
|
-
cachedAccessToken = AccessTokenEntity.createAccessTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.access_token || Constants.EMPTY_STRING, this.clientId,
|
|
5441
|
-
? idTokenObj.claims.tid || Constants.EMPTY_STRING
|
|
5442
|
-
: authority.tenant, responseScopes.printScopes(), tokenExpirationSeconds, extendedTokenExpirationSeconds, this.cryptoObj, refreshOnSeconds, serverTokenResponse.token_type, userAssertionHash, serverTokenResponse.key_id, request.claims, request.requestedClaimsHash);
|
|
5451
|
+
cachedAccessToken = AccessTokenEntity.createAccessTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.access_token || Constants.EMPTY_STRING, this.clientId, idTokenClaims?.tid || authority.tenant, responseScopes.printScopes(), tokenExpirationSeconds, extendedTokenExpirationSeconds, this.cryptoObj, refreshOnSeconds, serverTokenResponse.token_type, userAssertionHash, serverTokenResponse.key_id, request.claims, request.requestedClaimsHash);
|
|
5443
5452
|
}
|
|
5444
5453
|
// refreshToken
|
|
5445
5454
|
let cachedRefreshToken = null;
|
|
5446
|
-
if (
|
|
5455
|
+
if (serverTokenResponse.refresh_token) {
|
|
5447
5456
|
cachedRefreshToken = RefreshTokenEntity.createRefreshTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.refresh_token || Constants.EMPTY_STRING, this.clientId, serverTokenResponse.foci, userAssertionHash);
|
|
5448
5457
|
}
|
|
5449
5458
|
// appMetadata
|
|
5450
5459
|
let cachedAppMetadata = null;
|
|
5451
|
-
if (
|
|
5460
|
+
if (serverTokenResponse.foci) {
|
|
5452
5461
|
cachedAppMetadata = AppMetadataEntity.createAppMetadataEntity(this.clientId, env, serverTokenResponse.foci);
|
|
5453
5462
|
}
|
|
5454
5463
|
return new CacheRecord(cachedAccount, cachedIdToken, cachedAccessToken, cachedRefreshToken, cachedAppMetadata);
|
|
@@ -5463,11 +5472,12 @@ class ResponseHandler {
|
|
|
5463
5472
|
* @param fromTokenCache
|
|
5464
5473
|
* @param stateString
|
|
5465
5474
|
*/
|
|
5466
|
-
static async generateAuthenticationResult(cryptoObj, authority, cacheRecord, fromTokenCache, request,
|
|
5475
|
+
static async generateAuthenticationResult(cryptoObj, authority, cacheRecord, fromTokenCache, request, idTokenClaims, requestState, serverTokenResponse, requestId) {
|
|
5467
5476
|
let accessToken = Constants.EMPTY_STRING;
|
|
5468
5477
|
let responseScopes = [];
|
|
5469
5478
|
let expiresOn = null;
|
|
5470
5479
|
let extExpiresOn;
|
|
5480
|
+
let refreshOn;
|
|
5471
5481
|
let familyId = Constants.EMPTY_STRING;
|
|
5472
5482
|
if (cacheRecord.accessToken) {
|
|
5473
5483
|
if (cacheRecord.accessToken.tokenType === AuthenticationScheme.POP) {
|
|
@@ -5484,17 +5494,18 @@ class ResponseHandler {
|
|
|
5484
5494
|
responseScopes = ScopeSet.fromString(cacheRecord.accessToken.target).asArray();
|
|
5485
5495
|
expiresOn = new Date(Number(cacheRecord.accessToken.expiresOn) * 1000);
|
|
5486
5496
|
extExpiresOn = new Date(Number(cacheRecord.accessToken.extendedExpiresOn) * 1000);
|
|
5497
|
+
if (cacheRecord.accessToken.refreshOn) {
|
|
5498
|
+
refreshOn = new Date(Number(cacheRecord.accessToken.refreshOn) * 1000);
|
|
5499
|
+
}
|
|
5487
5500
|
}
|
|
5488
5501
|
if (cacheRecord.appMetadata) {
|
|
5489
5502
|
familyId =
|
|
5490
5503
|
cacheRecord.appMetadata.familyId === THE_FAMILY_ID
|
|
5491
5504
|
? THE_FAMILY_ID
|
|
5492
|
-
:
|
|
5505
|
+
: "";
|
|
5493
5506
|
}
|
|
5494
|
-
const uid =
|
|
5495
|
-
|
|
5496
|
-
Constants.EMPTY_STRING;
|
|
5497
|
-
const tid = idTokenObj?.claims.tid || Constants.EMPTY_STRING;
|
|
5507
|
+
const uid = idTokenClaims?.oid || idTokenClaims?.sub || "";
|
|
5508
|
+
const tid = idTokenClaims?.tid || "";
|
|
5498
5509
|
// for hybrid + native bridge enablement, send back the native account Id
|
|
5499
5510
|
if (serverTokenResponse?.spa_accountid && !!cacheRecord.account) {
|
|
5500
5511
|
cacheRecord.account.nativeAccountId =
|
|
@@ -5508,14 +5519,15 @@ class ResponseHandler {
|
|
|
5508
5519
|
account: cacheRecord.account
|
|
5509
5520
|
? cacheRecord.account.getAccountInfo()
|
|
5510
5521
|
: null,
|
|
5511
|
-
idToken:
|
|
5512
|
-
idTokenClaims:
|
|
5522
|
+
idToken: cacheRecord?.idToken?.secret || "",
|
|
5523
|
+
idTokenClaims: idTokenClaims || {},
|
|
5513
5524
|
accessToken: accessToken,
|
|
5514
5525
|
fromCache: fromTokenCache,
|
|
5515
5526
|
expiresOn: expiresOn,
|
|
5527
|
+
extExpiresOn: extExpiresOn,
|
|
5528
|
+
refreshOn: refreshOn,
|
|
5516
5529
|
correlationId: request.correlationId,
|
|
5517
5530
|
requestId: requestId || Constants.EMPTY_STRING,
|
|
5518
|
-
extExpiresOn: extExpiresOn,
|
|
5519
5531
|
familyId: familyId,
|
|
5520
5532
|
tokenType: cacheRecord.accessToken?.tokenType || Constants.EMPTY_STRING,
|
|
5521
5533
|
state: requestState
|
|
@@ -5530,6 +5542,92 @@ class ResponseHandler {
|
|
|
5530
5542
|
}
|
|
5531
5543
|
}
|
|
5532
5544
|
|
|
5545
|
+
/*
|
|
5546
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
5547
|
+
* Licensed under the MIT License.
|
|
5548
|
+
*/
|
|
5549
|
+
/**
|
|
5550
|
+
* Wraps a function with a performance measurement.
|
|
5551
|
+
* Usage: invoke(functionToCall, performanceClient, "EventName", "correlationId")(...argsToPassToFunction)
|
|
5552
|
+
* @param callback
|
|
5553
|
+
* @param eventName
|
|
5554
|
+
* @param logger
|
|
5555
|
+
* @param telemetryClient
|
|
5556
|
+
* @param correlationId
|
|
5557
|
+
* @returns
|
|
5558
|
+
* @internal
|
|
5559
|
+
*/
|
|
5560
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5561
|
+
const invoke = (callback, eventName, logger, telemetryClient, correlationId) => {
|
|
5562
|
+
return (...args) => {
|
|
5563
|
+
logger.trace(`Executing function ${eventName}`);
|
|
5564
|
+
const inProgressEvent = telemetryClient?.startMeasurement(eventName, correlationId);
|
|
5565
|
+
telemetryClient?.setPreQueueTime(eventName, correlationId);
|
|
5566
|
+
try {
|
|
5567
|
+
const result = callback(...args);
|
|
5568
|
+
inProgressEvent?.end({
|
|
5569
|
+
success: true,
|
|
5570
|
+
});
|
|
5571
|
+
logger.trace(`Returning result from ${eventName}`);
|
|
5572
|
+
return result;
|
|
5573
|
+
}
|
|
5574
|
+
catch (e) {
|
|
5575
|
+
logger.trace(`Error occurred in ${eventName}`);
|
|
5576
|
+
try {
|
|
5577
|
+
logger.trace(JSON.stringify(e));
|
|
5578
|
+
}
|
|
5579
|
+
catch (e) {
|
|
5580
|
+
logger.trace("Unable to print error message.");
|
|
5581
|
+
}
|
|
5582
|
+
inProgressEvent?.end({
|
|
5583
|
+
success: false,
|
|
5584
|
+
});
|
|
5585
|
+
throw e;
|
|
5586
|
+
}
|
|
5587
|
+
};
|
|
5588
|
+
};
|
|
5589
|
+
/**
|
|
5590
|
+
* Wraps an async function with a performance measurement.
|
|
5591
|
+
* Usage: invokeAsync(functionToCall, performanceClient, "EventName", "correlationId")(...argsToPassToFunction)
|
|
5592
|
+
* @param callback
|
|
5593
|
+
* @param eventName
|
|
5594
|
+
* @param logger
|
|
5595
|
+
* @param telemetryClient
|
|
5596
|
+
* @param correlationId
|
|
5597
|
+
* @returns
|
|
5598
|
+
* @internal
|
|
5599
|
+
*
|
|
5600
|
+
*/
|
|
5601
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5602
|
+
const invokeAsync = (callback, eventName, logger, telemetryClient, correlationId) => {
|
|
5603
|
+
return (...args) => {
|
|
5604
|
+
logger.trace(`Executing function ${eventName}`);
|
|
5605
|
+
const inProgressEvent = telemetryClient?.startMeasurement(eventName, correlationId);
|
|
5606
|
+
telemetryClient?.setPreQueueTime(eventName, correlationId);
|
|
5607
|
+
return callback(...args)
|
|
5608
|
+
.then((response) => {
|
|
5609
|
+
logger.trace(`Returning result from ${eventName}`);
|
|
5610
|
+
inProgressEvent?.end({
|
|
5611
|
+
success: true,
|
|
5612
|
+
});
|
|
5613
|
+
return response;
|
|
5614
|
+
})
|
|
5615
|
+
.catch((e) => {
|
|
5616
|
+
logger.trace(`Error occurred in ${eventName}`);
|
|
5617
|
+
try {
|
|
5618
|
+
logger.trace(JSON.stringify(e));
|
|
5619
|
+
}
|
|
5620
|
+
catch (e) {
|
|
5621
|
+
logger.trace("Unable to print error message.");
|
|
5622
|
+
}
|
|
5623
|
+
inProgressEvent?.end({
|
|
5624
|
+
success: false,
|
|
5625
|
+
});
|
|
5626
|
+
throw e;
|
|
5627
|
+
});
|
|
5628
|
+
};
|
|
5629
|
+
};
|
|
5630
|
+
|
|
5533
5631
|
/*
|
|
5534
5632
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
5535
5633
|
* Licensed under the MIT License.
|
|
@@ -5558,8 +5656,7 @@ class AuthorizationCodeClient extends BaseClient {
|
|
|
5558
5656
|
*/
|
|
5559
5657
|
async getAuthCodeUrl(request) {
|
|
5560
5658
|
this.performanceClient?.addQueueMeasurement(PerformanceEvents.GetAuthCodeUrl, request.correlationId);
|
|
5561
|
-
this.
|
|
5562
|
-
const queryString = await this.createAuthCodeUrlQueryString(request);
|
|
5659
|
+
const queryString = await invokeAsync(this.createAuthCodeUrlQueryString.bind(this), PerformanceEvents.AuthClientCreateQueryString, this.logger, this.performanceClient, request.correlationId)(request);
|
|
5563
5660
|
return UrlString.appendQueryString(this.authority.authorizationEndpoint, queryString);
|
|
5564
5661
|
}
|
|
5565
5662
|
/**
|
|
@@ -5568,46 +5665,18 @@ class AuthorizationCodeClient extends BaseClient {
|
|
|
5568
5665
|
* @param request
|
|
5569
5666
|
*/
|
|
5570
5667
|
async acquireToken(request, authCodePayload) {
|
|
5571
|
-
|
|
5668
|
+
this.performanceClient?.addQueueMeasurement(PerformanceEvents.AuthClientAcquireToken, request.correlationId);
|
|
5669
|
+
if (!request.code) {
|
|
5572
5670
|
throw ClientAuthError.createTokenRequestCannotBeMadeError();
|
|
5573
5671
|
}
|
|
5574
|
-
this.performanceClient?.addQueueMeasurement(PerformanceEvents.AuthClientAcquireToken, request.correlationId);
|
|
5575
|
-
const atsMeasurement = this.performanceClient?.startMeasurement(
|
|
5576
|
-
// @ts-ignore
|
|
5577
|
-
"AuthCodeClientAcquireToken", request.correlationId);
|
|
5578
|
-
this.logger.info("in acquireToken call in auth-code client");
|
|
5579
5672
|
const reqTimestamp = TimeUtils.nowSeconds();
|
|
5580
|
-
this.
|
|
5581
|
-
const response = await this.executeTokenRequest(this.authority, request);
|
|
5673
|
+
const response = await invokeAsync(this.executeTokenRequest.bind(this), PerformanceEvents.AuthClientExecuteTokenRequest, this.logger, this.performanceClient, request.correlationId)(this.authority, request);
|
|
5582
5674
|
// Retrieve requestId from response headers
|
|
5583
5675
|
const requestId = response.headers?.[HeaderNames.X_MS_REQUEST_ID];
|
|
5584
|
-
const httpVerAuthority = response.headers?.[HeaderNames.X_MS_HTTP_VERSION];
|
|
5585
|
-
if (httpVerAuthority) {
|
|
5586
|
-
atsMeasurement?.add({
|
|
5587
|
-
httpVerAuthority,
|
|
5588
|
-
});
|
|
5589
|
-
}
|
|
5590
5676
|
const responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin, this.performanceClient);
|
|
5591
5677
|
// Validate response. This function throws a server error if an error is returned by the server.
|
|
5592
5678
|
responseHandler.validateTokenResponse(response.body);
|
|
5593
|
-
|
|
5594
|
-
return responseHandler
|
|
5595
|
-
.handleServerTokenResponse(response.body, this.authority, reqTimestamp, request, authCodePayload, undefined, undefined, undefined, requestId)
|
|
5596
|
-
.then((result) => {
|
|
5597
|
-
atsMeasurement?.end({
|
|
5598
|
-
success: true,
|
|
5599
|
-
});
|
|
5600
|
-
return result;
|
|
5601
|
-
})
|
|
5602
|
-
.catch((error) => {
|
|
5603
|
-
this.logger.verbose("Error in fetching token in ACC", request.correlationId);
|
|
5604
|
-
atsMeasurement?.end({
|
|
5605
|
-
errorCode: error.errorCode,
|
|
5606
|
-
subErrorCode: error.subError,
|
|
5607
|
-
success: false,
|
|
5608
|
-
});
|
|
5609
|
-
throw error;
|
|
5610
|
-
});
|
|
5679
|
+
return invokeAsync(responseHandler.handleServerTokenResponse.bind(responseHandler), PerformanceEvents.HandleServerTokenResponse, this.logger, this.performanceClient, request.correlationId)(response.body, this.authority, reqTimestamp, request, authCodePayload, undefined, undefined, undefined, requestId);
|
|
5611
5680
|
}
|
|
5612
5681
|
/**
|
|
5613
5682
|
* Handles the hash fragment response from public client code request. Returns a code response used by
|
|
@@ -5652,10 +5721,9 @@ class AuthorizationCodeClient extends BaseClient {
|
|
|
5652
5721
|
*/
|
|
5653
5722
|
async executeTokenRequest(authority, request) {
|
|
5654
5723
|
this.performanceClient?.addQueueMeasurement(PerformanceEvents.AuthClientExecuteTokenRequest, request.correlationId);
|
|
5655
|
-
this.performanceClient?.setPreQueueTime(PerformanceEvents.AuthClientCreateTokenRequestBody, request.correlationId);
|
|
5656
5724
|
const queryParametersString = this.createTokenQueryParameters(request);
|
|
5657
5725
|
const endpoint = UrlString.appendQueryString(authority.tokenEndpoint, queryParametersString);
|
|
5658
|
-
const requestBody = await this.createTokenRequestBody(request);
|
|
5726
|
+
const requestBody = await invokeAsync(this.createTokenRequestBody.bind(this), PerformanceEvents.AuthClientCreateTokenRequestBody, this.logger, this.performanceClient, request.correlationId)(request);
|
|
5659
5727
|
let ccsCredential = undefined;
|
|
5660
5728
|
if (request.clientInfo) {
|
|
5661
5729
|
try {
|
|
@@ -5681,7 +5749,7 @@ class AuthorizationCodeClient extends BaseClient {
|
|
|
5681
5749
|
shrClaims: request.shrClaims,
|
|
5682
5750
|
sshKid: request.sshKid,
|
|
5683
5751
|
};
|
|
5684
|
-
return this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint);
|
|
5752
|
+
return invokeAsync(this.executePostToTokenEndpoint.bind(this), PerformanceEvents.BaseClientExecutePostToTokenEndpoint, this.logger, this.performanceClient, request.correlationId)(endpoint, requestBody, headers, thumbprint, request.correlationId);
|
|
5685
5753
|
}
|
|
5686
5754
|
/**
|
|
5687
5755
|
* Generates a map for all the params to be sent to the service
|
|
@@ -5910,7 +5978,7 @@ class AuthorizationCodeClient extends BaseClient {
|
|
|
5910
5978
|
if (request.state) {
|
|
5911
5979
|
parameterBuilder.addState(request.state);
|
|
5912
5980
|
}
|
|
5913
|
-
if (
|
|
5981
|
+
if (request.claims ||
|
|
5914
5982
|
(this.config.authOptions.clientCapabilities &&
|
|
5915
5983
|
this.config.authOptions.clientCapabilities.length > 0)) {
|
|
5916
5984
|
parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities);
|
|
@@ -5988,15 +6056,6 @@ class RefreshTokenClient extends BaseClient {
|
|
|
5988
6056
|
const reqTimestamp = TimeUtils.nowSeconds();
|
|
5989
6057
|
this.performanceClient?.setPreQueueTime(PerformanceEvents.RefreshTokenClientExecuteTokenRequest, request.correlationId);
|
|
5990
6058
|
const response = await this.executeTokenRequest(request, this.authority);
|
|
5991
|
-
const httpVerToken = response.headers?.[HeaderNames.X_MS_HTTP_VERSION];
|
|
5992
|
-
atsMeasurement?.add({
|
|
5993
|
-
refreshTokenSize: response.body.refresh_token?.length || 0,
|
|
5994
|
-
});
|
|
5995
|
-
if (httpVerToken) {
|
|
5996
|
-
atsMeasurement?.add({
|
|
5997
|
-
httpVerToken,
|
|
5998
|
-
});
|
|
5999
|
-
}
|
|
6000
6059
|
// Retrieve requestId from response headers
|
|
6001
6060
|
const requestId = response.headers?.[HeaderNames.X_MS_REQUEST_ID];
|
|
6002
6061
|
const responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin);
|
|
@@ -6119,7 +6178,7 @@ class RefreshTokenClient extends BaseClient {
|
|
|
6119
6178
|
shrClaims: request.shrClaims,
|
|
6120
6179
|
sshKid: request.sshKid,
|
|
6121
6180
|
};
|
|
6122
|
-
return this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint)
|
|
6181
|
+
return this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint, request.correlationId)
|
|
6123
6182
|
.then((result) => {
|
|
6124
6183
|
acquireTokenMeasurement?.end({
|
|
6125
6184
|
success: true,
|
|
@@ -6296,19 +6355,19 @@ class SilentFlowClient extends BaseClient {
|
|
|
6296
6355
|
* @param cacheRecord
|
|
6297
6356
|
*/
|
|
6298
6357
|
async generateResultFromCacheRecord(cacheRecord, request) {
|
|
6299
|
-
let
|
|
6358
|
+
let idTokenClaims;
|
|
6300
6359
|
if (cacheRecord.idToken) {
|
|
6301
|
-
|
|
6360
|
+
idTokenClaims = extractTokenClaims(cacheRecord.idToken.secret, this.config.cryptoInterface.base64Decode);
|
|
6302
6361
|
}
|
|
6303
6362
|
// token max_age check
|
|
6304
6363
|
if (request.maxAge || request.maxAge === 0) {
|
|
6305
|
-
const authTime =
|
|
6364
|
+
const authTime = idTokenClaims?.auth_time;
|
|
6306
6365
|
if (!authTime) {
|
|
6307
6366
|
throw ClientAuthError.createAuthTimeNotFoundError();
|
|
6308
6367
|
}
|
|
6309
|
-
|
|
6368
|
+
checkMaxAge(authTime, request.maxAge);
|
|
6310
6369
|
}
|
|
6311
|
-
return await ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, cacheRecord, true, request,
|
|
6370
|
+
return await ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, cacheRecord, true, request, idTokenClaims);
|
|
6312
6371
|
}
|
|
6313
6372
|
}
|
|
6314
6373
|
|
|
@@ -8220,7 +8279,7 @@ class AuthorityFactory {
|
|
|
8220
8279
|
*/
|
|
8221
8280
|
static createInstance(authorityUrl, networkInterface, cacheManager, authorityOptions, logger, performanceClient, correlationId) {
|
|
8222
8281
|
// Throw error if authority url is empty
|
|
8223
|
-
if (
|
|
8282
|
+
if (!authorityUrl) {
|
|
8224
8283
|
throw ClientConfigurationError.createUrlEmptyError();
|
|
8225
8284
|
}
|
|
8226
8285
|
return new Authority(authorityUrl, networkInterface, cacheManager, authorityOptions, logger, performanceClient, correlationId);
|
|
@@ -8505,10 +8564,10 @@ class ServerTelemetryManager {
|
|
|
8505
8564
|
lastRequests.failedRequests.push(this.apiId, this.correlationId);
|
|
8506
8565
|
if (error instanceof Error && !!error && error.toString()) {
|
|
8507
8566
|
if (error instanceof AuthError) {
|
|
8508
|
-
if (
|
|
8567
|
+
if (error.subError) {
|
|
8509
8568
|
lastRequests.errors.push(error.subError);
|
|
8510
8569
|
}
|
|
8511
|
-
else if (
|
|
8570
|
+
else if (error.errorCode) {
|
|
8512
8571
|
lastRequests.errors.push(error.errorCode);
|
|
8513
8572
|
}
|
|
8514
8573
|
else {
|
|
@@ -9050,10 +9109,30 @@ class StubPerformanceMeasurement {
|
|
|
9050
9109
|
return null;
|
|
9051
9110
|
}
|
|
9052
9111
|
}
|
|
9053
|
-
class StubPerformanceClient
|
|
9112
|
+
class StubPerformanceClient {
|
|
9054
9113
|
generateId() {
|
|
9055
9114
|
return "callback-id";
|
|
9056
9115
|
}
|
|
9116
|
+
startMeasurement(measureName, correlationId) {
|
|
9117
|
+
return {
|
|
9118
|
+
end: () => null,
|
|
9119
|
+
discard: () => { },
|
|
9120
|
+
add: () => { },
|
|
9121
|
+
increment: () => { },
|
|
9122
|
+
event: {
|
|
9123
|
+
eventId: this.generateId(),
|
|
9124
|
+
status: PerformanceEventStatus.InProgress,
|
|
9125
|
+
authority: "",
|
|
9126
|
+
libraryName: "",
|
|
9127
|
+
libraryVersion: "",
|
|
9128
|
+
clientId: "",
|
|
9129
|
+
name: measureName,
|
|
9130
|
+
startTimeMs: Date.now(),
|
|
9131
|
+
correlationId: correlationId || "",
|
|
9132
|
+
},
|
|
9133
|
+
measurement: new StubPerformanceMeasurement(),
|
|
9134
|
+
};
|
|
9135
|
+
}
|
|
9057
9136
|
startPerformanceMeasurement() {
|
|
9058
9137
|
return new StubPerformanceMeasurement();
|
|
9059
9138
|
}
|
|
@@ -9130,7 +9209,7 @@ exports.DefaultStorageClass = DefaultStorageClass;
|
|
|
9130
9209
|
exports.Errors = Errors;
|
|
9131
9210
|
exports.GrantType = GrantType;
|
|
9132
9211
|
exports.HeaderNames = HeaderNames;
|
|
9133
|
-
exports.
|
|
9212
|
+
exports.HttpStatus = HttpStatus;
|
|
9134
9213
|
exports.IdTokenEntity = IdTokenEntity;
|
|
9135
9214
|
exports.IntFields = IntFields;
|
|
9136
9215
|
exports.InteractionRequiredAuthError = InteractionRequiredAuthError;
|
|
@@ -9173,5 +9252,7 @@ exports.TokenCacheContext = TokenCacheContext;
|
|
|
9173
9252
|
exports.UrlString = UrlString;
|
|
9174
9253
|
exports.buildClientInfo = buildClientInfo;
|
|
9175
9254
|
exports.buildClientInfoFromHomeAccountId = buildClientInfoFromHomeAccountId;
|
|
9255
|
+
exports.invoke = invoke;
|
|
9256
|
+
exports.invokeAsync = invokeAsync;
|
|
9176
9257
|
exports.version = version;
|
|
9177
9258
|
//# sourceMappingURL=index.cjs.map
|