@azure/msal-common 14.0.1 → 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.d.ts +1 -0
- package/dist/authority/Authority.d.ts.map +1 -1
- package/dist/authority/Authority.mjs +4 -2
- package/dist/authority/Authority.mjs.map +1 -1
- package/dist/authority/AuthorityFactory.d.ts +1 -0
- package/dist/authority/AuthorityFactory.d.ts.map +1 -1
- package/dist/authority/AuthorityFactory.mjs +3 -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 +2 -0
- package/dist/cache/CacheManager.d.ts.map +1 -1
- package/dist/cache/CacheManager.mjs +7 -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 +1 -0
- package/dist/cache/entities/AccountEntity.d.ts.map +1 -1
- package/dist/cache/entities/AccountEntity.mjs +3 -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.d.ts +1 -0
- package/dist/cache/entities/AuthorityMetadataEntity.d.ts.map +1 -1
- package/dist/cache/entities/AuthorityMetadataEntity.mjs +2 -1
- package/dist/cache/entities/AuthorityMetadataEntity.mjs.map +1 -1
- package/dist/cache/entities/CacheRecord.d.ts +1 -0
- package/dist/cache/entities/CacheRecord.d.ts.map +1 -1
- package/dist/cache/entities/CacheRecord.mjs +2 -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/cache/utils/CacheTypes.d.ts +7 -0
- package/dist/cache/utils/CacheTypes.d.ts.map +1 -1
- package/dist/client/AuthorizationCodeClient.d.ts +1 -0
- package/dist/client/AuthorizationCodeClient.d.ts.map +1 -1
- package/dist/client/AuthorizationCodeClient.mjs +11 -39
- package/dist/client/AuthorizationCodeClient.mjs.map +1 -1
- package/dist/client/BaseClient.d.ts +2 -1
- package/dist/client/BaseClient.d.ts.map +1 -1
- package/dist/client/BaseClient.mjs +9 -2
- package/dist/client/BaseClient.mjs.map +1 -1
- package/dist/client/RefreshTokenClient.d.ts +1 -0
- package/dist/client/RefreshTokenClient.d.ts.map +1 -1
- package/dist/client/RefreshTokenClient.mjs +3 -11
- package/dist/client/RefreshTokenClient.mjs.map +1 -1
- package/dist/client/SilentFlowClient.d.ts +1 -0
- package/dist/client/SilentFlowClient.d.ts.map +1 -1
- package/dist/client/SilentFlowClient.mjs +8 -7
- package/dist/client/SilentFlowClient.mjs.map +1 -1
- package/dist/config/ClientConfiguration.d.ts +2 -0
- package/dist/config/ClientConfiguration.d.ts.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.d.ts +1 -0
- package/dist/crypto/JoseHeader.d.ts.map +1 -1
- package/dist/crypto/JoseHeader.mjs +2 -1
- package/dist/crypto/JoseHeader.mjs.map +1 -1
- package/dist/crypto/PopTokenGenerator.d.ts +1 -0
- package/dist/crypto/PopTokenGenerator.d.ts.map +1 -1
- package/dist/crypto/PopTokenGenerator.mjs +2 -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 +1926 -1826
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -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.d.ts +1 -0
- package/dist/network/NetworkManager.d.ts.map +1 -1
- package/dist/network/NetworkManager.mjs +2 -1
- package/dist/network/NetworkManager.mjs.map +1 -1
- package/dist/network/ThrottlingUtils.d.ts +1 -0
- package/dist/network/ThrottlingUtils.d.ts.map +1 -1
- package/dist/network/ThrottlingUtils.mjs +2 -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 +1 -0
- package/dist/request/RequestParameterBuilder.d.ts.map +1 -1
- package/dist/request/RequestParameterBuilder.mjs +7 -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 +5 -3
- package/dist/response/ResponseHandler.d.ts.map +1 -1
- package/dist/response/ResponseHandler.mjs +58 -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 +1 -0
- package/dist/telemetry/server/ServerTelemetryManager.d.ts.map +1 -1
- package/dist/telemetry/server/ServerTelemetryManager.mjs +4 -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.1";
|
|
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);
|
|
@@ -1890,6 +1861,7 @@ const ProtocolMode = {
|
|
|
1890
1861
|
* idTokenClaims: Object containing claims parsed from ID token
|
|
1891
1862
|
* nativeAccountId: Account identifier on the native device
|
|
1892
1863
|
* }
|
|
1864
|
+
* @internal
|
|
1893
1865
|
*/
|
|
1894
1866
|
class AccountEntity {
|
|
1895
1867
|
/**
|
|
@@ -2029,8 +2001,7 @@ class AccountEntity {
|
|
|
2029
2001
|
if (serverClientInfo) {
|
|
2030
2002
|
try {
|
|
2031
2003
|
const clientInfo = buildClientInfo(serverClientInfo, cryptoObj);
|
|
2032
|
-
if (
|
|
2033
|
-
!StringUtils.isEmpty(clientInfo.utid)) {
|
|
2004
|
+
if (clientInfo.uid && clientInfo.utid) {
|
|
2034
2005
|
return `${clientInfo.uid}${Separators.CLIENT_INFO_SEPARATOR}${clientInfo.utid}`;
|
|
2035
2006
|
}
|
|
2036
2007
|
}
|
|
@@ -2091,56 +2062,74 @@ class AccountEntity {
|
|
|
2091
2062
|
* Licensed under the MIT License.
|
|
2092
2063
|
*/
|
|
2093
2064
|
/**
|
|
2094
|
-
*
|
|
2065
|
+
* Extract token by decoding the rawToken
|
|
2066
|
+
*
|
|
2067
|
+
* @param encodedToken
|
|
2095
2068
|
*/
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
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);
|
|
2103
2076
|
}
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
}
|
|
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)}`);
|
|
2121
2094
|
}
|
|
2122
2095
|
/**
|
|
2123
|
-
*
|
|
2096
|
+
* const crackedToken = {
|
|
2097
|
+
* header: matches[1],
|
|
2098
|
+
* JWSPayload: matches[2],
|
|
2099
|
+
* JWSSig: matches[3],
|
|
2100
|
+
* };
|
|
2124
2101
|
*/
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
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();
|
|
2135
2116
|
}
|
|
2136
2117
|
}
|
|
2137
2118
|
|
|
2119
|
+
var AuthToken = /*#__PURE__*/Object.freeze({
|
|
2120
|
+
__proto__: null,
|
|
2121
|
+
checkMaxAge: checkMaxAge,
|
|
2122
|
+
extractTokenClaims: extractTokenClaims,
|
|
2123
|
+
getJWSPayload: getJWSPayload
|
|
2124
|
+
});
|
|
2125
|
+
|
|
2138
2126
|
/*
|
|
2139
2127
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
2140
2128
|
* Licensed under the MIT License.
|
|
2141
2129
|
*/
|
|
2142
2130
|
/**
|
|
2143
2131
|
* Interface class which implement cache storage functions used by MSAL to perform validity checks, and store tokens.
|
|
2132
|
+
* @internal
|
|
2144
2133
|
*/
|
|
2145
2134
|
class CacheManager {
|
|
2146
2135
|
constructor(clientId, cryptoImpl, logger) {
|
|
@@ -2191,7 +2180,7 @@ class CacheManager {
|
|
|
2191
2180
|
const idToken = this.getIdToken(accountInfo);
|
|
2192
2181
|
if (idToken) {
|
|
2193
2182
|
accountInfo.idToken = idToken.secret;
|
|
2194
|
-
accountInfo.idTokenClaims =
|
|
2183
|
+
accountInfo.idTokenClaims = extractTokenClaims(idToken.secret, this.cryptoImpl.base64Decode);
|
|
2195
2184
|
}
|
|
2196
2185
|
return accountInfo;
|
|
2197
2186
|
}
|
|
@@ -2587,7 +2576,7 @@ class CacheManager {
|
|
|
2587
2576
|
const cachedRefreshToken = this.getRefreshToken(account, false, tokenKeys);
|
|
2588
2577
|
const cachedAppMetadata = this.readAppMetadataFromCache(environment);
|
|
2589
2578
|
if (cachedAccount && cachedIdToken) {
|
|
2590
|
-
cachedAccount.idTokenClaims =
|
|
2579
|
+
cachedAccount.idTokenClaims = extractTokenClaims(cachedIdToken.secret, this.cryptoImpl.base64Decode);
|
|
2591
2580
|
}
|
|
2592
2581
|
return {
|
|
2593
2582
|
account: cachedAccount,
|
|
@@ -2743,7 +2732,7 @@ class CacheManager {
|
|
|
2743
2732
|
else if (numAccessTokens > 1) {
|
|
2744
2733
|
this.commonLogger.info("CacheManager:getAccessToken - Multiple access tokens found, clearing them");
|
|
2745
2734
|
accessTokens.forEach((accessToken) => {
|
|
2746
|
-
this.removeAccessToken(accessToken.generateCredentialKey());
|
|
2735
|
+
void this.removeAccessToken(accessToken.generateCredentialKey());
|
|
2747
2736
|
});
|
|
2748
2737
|
return null;
|
|
2749
2738
|
}
|
|
@@ -3057,6 +3046,7 @@ class CacheManager {
|
|
|
3057
3046
|
return obj;
|
|
3058
3047
|
}
|
|
3059
3048
|
}
|
|
3049
|
+
/** @internal */
|
|
3060
3050
|
class DefaultStorageClass extends CacheManager {
|
|
3061
3051
|
setAccount() {
|
|
3062
3052
|
const notImplErr = "Storage interface - setAccount() has not been implemented for the cacheStorage interface.";
|
|
@@ -3275,6 +3265,7 @@ class ServerError extends AuthError {
|
|
|
3275
3265
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3276
3266
|
* Licensed under the MIT License.
|
|
3277
3267
|
*/
|
|
3268
|
+
/** @internal */
|
|
3278
3269
|
class ThrottlingUtils {
|
|
3279
3270
|
/**
|
|
3280
3271
|
* Prepares a RequestThumbprint to be stored as a key.
|
|
@@ -3370,6 +3361,7 @@ class ThrottlingUtils {
|
|
|
3370
3361
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3371
3362
|
* Licensed under the MIT License.
|
|
3372
3363
|
*/
|
|
3364
|
+
/** @internal */
|
|
3373
3365
|
class NetworkManager {
|
|
3374
3366
|
constructor(networkClient, cacheManager) {
|
|
3375
3367
|
this.networkClient = networkClient;
|
|
@@ -3422,7 +3414,7 @@ class RequestValidator {
|
|
|
3422
3414
|
* @param redirectUri
|
|
3423
3415
|
*/
|
|
3424
3416
|
static validateRedirectUri(redirectUri) {
|
|
3425
|
-
if (
|
|
3417
|
+
if (!redirectUri) {
|
|
3426
3418
|
throw ClientConfigurationError.createRedirectUriEmptyError();
|
|
3427
3419
|
}
|
|
3428
3420
|
}
|
|
@@ -3453,8 +3445,7 @@ class RequestValidator {
|
|
|
3453
3445
|
* @param codeChallengeMethod
|
|
3454
3446
|
*/
|
|
3455
3447
|
static validateCodeChallengeParams(codeChallenge, codeChallengeMethod) {
|
|
3456
|
-
if (
|
|
3457
|
-
StringUtils.isEmpty(codeChallengeMethod)) {
|
|
3448
|
+
if (!codeChallenge || !codeChallengeMethod) {
|
|
3458
3449
|
throw ClientConfigurationError.createInvalidCodeChallengeParamsError();
|
|
3459
3450
|
}
|
|
3460
3451
|
else {
|
|
@@ -3482,7 +3473,7 @@ class RequestValidator {
|
|
|
3482
3473
|
return {};
|
|
3483
3474
|
}
|
|
3484
3475
|
// Remove any query parameters already included in SSO params
|
|
3485
|
-
queryParams.forEach((
|
|
3476
|
+
queryParams.forEach((_value, key) => {
|
|
3486
3477
|
if (eQParams[key]) {
|
|
3487
3478
|
delete eQParams[key];
|
|
3488
3479
|
}
|
|
@@ -3496,6 +3487,7 @@ class RequestValidator {
|
|
|
3496
3487
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3497
3488
|
* Licensed under the MIT License.
|
|
3498
3489
|
*/
|
|
3490
|
+
/** @internal */
|
|
3499
3491
|
class RequestParameterBuilder {
|
|
3500
3492
|
constructor() {
|
|
3501
3493
|
this.parameters = new Map();
|
|
@@ -3664,7 +3656,7 @@ class RequestParameterBuilder {
|
|
|
3664
3656
|
* @param state
|
|
3665
3657
|
*/
|
|
3666
3658
|
addState(state) {
|
|
3667
|
-
if (
|
|
3659
|
+
if (state) {
|
|
3668
3660
|
this.parameters.set(AADServerParamKeys.STATE, encodeURIComponent(state));
|
|
3669
3661
|
}
|
|
3670
3662
|
}
|
|
@@ -3731,7 +3723,7 @@ class RequestParameterBuilder {
|
|
|
3731
3723
|
* @param clientAssertion
|
|
3732
3724
|
*/
|
|
3733
3725
|
addClientAssertion(clientAssertion) {
|
|
3734
|
-
if (
|
|
3726
|
+
if (clientAssertion) {
|
|
3735
3727
|
this.parameters.set(AADServerParamKeys.CLIENT_ASSERTION, encodeURIComponent(clientAssertion));
|
|
3736
3728
|
}
|
|
3737
3729
|
}
|
|
@@ -3740,7 +3732,7 @@ class RequestParameterBuilder {
|
|
|
3740
3732
|
* @param clientAssertionType
|
|
3741
3733
|
*/
|
|
3742
3734
|
addClientAssertionType(clientAssertionType) {
|
|
3743
|
-
if (
|
|
3735
|
+
if (clientAssertionType) {
|
|
3744
3736
|
this.parameters.set(AADServerParamKeys.CLIENT_ASSERTION_TYPE, encodeURIComponent(clientAssertionType));
|
|
3745
3737
|
}
|
|
3746
3738
|
}
|
|
@@ -3827,7 +3819,7 @@ class RequestParameterBuilder {
|
|
|
3827
3819
|
* @param cnfString
|
|
3828
3820
|
*/
|
|
3829
3821
|
addPopToken(cnfString) {
|
|
3830
|
-
if (
|
|
3822
|
+
if (cnfString) {
|
|
3831
3823
|
this.parameters.set(AADServerParamKeys.TOKEN_TYPE, AuthenticationScheme.POP);
|
|
3832
3824
|
this.parameters.set(AADServerParamKeys.REQ_CNF, encodeURIComponent(cnfString));
|
|
3833
3825
|
}
|
|
@@ -3836,7 +3828,7 @@ class RequestParameterBuilder {
|
|
|
3836
3828
|
* add SSH JWK and key ID to query params
|
|
3837
3829
|
*/
|
|
3838
3830
|
addSshJwk(sshJwkString) {
|
|
3839
|
-
if (
|
|
3831
|
+
if (sshJwkString) {
|
|
3840
3832
|
this.parameters.set(AADServerParamKeys.TOKEN_TYPE, AuthenticationScheme.SSH);
|
|
3841
3833
|
this.parameters.set(AADServerParamKeys.REQ_CNF, encodeURIComponent(sshJwkString));
|
|
3842
3834
|
}
|
|
@@ -3878,18 +3870,254 @@ class RequestParameterBuilder {
|
|
|
3878
3870
|
* Licensed under the MIT License.
|
|
3879
3871
|
*/
|
|
3880
3872
|
/**
|
|
3881
|
-
*
|
|
3873
|
+
* Enumeration of operations that are instrumented by have their performance measured by the PerformanceClient.
|
|
3874
|
+
*
|
|
3875
|
+
* @export
|
|
3876
|
+
* @enum {number}
|
|
3882
3877
|
*/
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3890
|
-
|
|
3891
|
-
|
|
3892
|
-
|
|
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
|
|
4120
|
+
this.cacheManager = this.config.storageInterface;
|
|
3893
4121
|
// Set the network interface
|
|
3894
4122
|
this.networkClient = this.config.networkInterface;
|
|
3895
4123
|
// Set the NetworkManager
|
|
@@ -3923,623 +4151,51 @@ class BaseClient {
|
|
|
3923
4151
|
headers[HeaderNames.CCS_HEADER] = `UPN: ${ccsCred.credential}`;
|
|
3924
4152
|
break;
|
|
3925
4153
|
}
|
|
3926
|
-
}
|
|
3927
|
-
return headers;
|
|
3928
|
-
}
|
|
3929
|
-
/**
|
|
3930
|
-
* Http post to token endpoint
|
|
3931
|
-
* @param tokenEndpoint
|
|
3932
|
-
* @param queryString
|
|
3933
|
-
* @param headers
|
|
3934
|
-
* @param thumbprint
|
|
3935
|
-
*/
|
|
3936
|
-
async executePostToTokenEndpoint(tokenEndpoint, queryString, headers, thumbprint) {
|
|
3937
|
-
const response = await this.networkManager.sendPostRequest(thumbprint, tokenEndpoint, { body: queryString, headers: headers });
|
|
3938
|
-
if (this.config.serverTelemetryManager &&
|
|
3939
|
-
response.status < 500 &&
|
|
3940
|
-
response.status !== 429) {
|
|
3941
|
-
// Telemetry data successfully logged by server, clear Telemetry cache
|
|
3942
|
-
this.config.serverTelemetryManager.clearTelemetryCache();
|
|
3943
|
-
}
|
|
3944
|
-
return response;
|
|
3945
|
-
}
|
|
3946
|
-
/**
|
|
3947
|
-
* Updates the authority object of the client. Endpoint discovery must be completed.
|
|
3948
|
-
* @param updatedAuthority
|
|
3949
|
-
*/
|
|
3950
|
-
updateAuthority(updatedAuthority) {
|
|
3951
|
-
if (!updatedAuthority.discoveryComplete()) {
|
|
3952
|
-
throw ClientAuthError.createEndpointDiscoveryIncompleteError("Updated authority has not completed endpoint discovery.");
|
|
3953
|
-
}
|
|
3954
|
-
this.authority = updatedAuthority;
|
|
3955
|
-
}
|
|
3956
|
-
/**
|
|
3957
|
-
* Creates query string for the /token request
|
|
3958
|
-
* @param request
|
|
3959
|
-
*/
|
|
3960
|
-
createTokenQueryParameters(request) {
|
|
3961
|
-
const parameterBuilder = new RequestParameterBuilder();
|
|
3962
|
-
if (request.tokenQueryParameters) {
|
|
3963
|
-
parameterBuilder.addExtraQueryParameters(request.tokenQueryParameters);
|
|
3964
|
-
}
|
|
3965
|
-
return parameterBuilder.createQueryString();
|
|
3966
|
-
}
|
|
3967
|
-
}
|
|
3968
|
-
|
|
3969
|
-
/*
|
|
3970
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
3971
|
-
* Licensed under the MIT License.
|
|
3972
|
-
*/
|
|
3973
|
-
/**
|
|
3974
|
-
* Base type for credentials to be stored in the cache: eg: ACCESS_TOKEN, ID_TOKEN etc
|
|
3975
|
-
*
|
|
3976
|
-
* Key:Value Schema:
|
|
3977
|
-
*
|
|
3978
|
-
* Key: <home_account_id*>-<environment>-<credential_type>-<client_id>-<realm*>-<target*>-<requestedClaims*>-<scheme*>
|
|
3979
|
-
*
|
|
3980
|
-
* Value Schema:
|
|
3981
|
-
* {
|
|
3982
|
-
* homeAccountId: home account identifier for the auth scheme,
|
|
3983
|
-
* environment: entity that issued the token, represented as a full host
|
|
3984
|
-
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
|
3985
|
-
* clientId: client ID of the application
|
|
3986
|
-
* secret: Actual credential as a string
|
|
3987
|
-
* familyId: Family ID identifier, usually only used for refresh tokens
|
|
3988
|
-
* realm: Full tenant or organizational identifier that the account belongs to
|
|
3989
|
-
* target: Permissions that are included in the token, or for refresh tokens, the resource identifier.
|
|
3990
|
-
* tokenType: Matches the authentication scheme for which the token was issued (i.e. Bearer or pop)
|
|
3991
|
-
* requestedClaimsHash: Matches the SHA 256 hash of the claims object included in the token request
|
|
3992
|
-
* userAssertionHash: Matches the SHA 256 hash of the obo_assertion for the OBO flow
|
|
3993
|
-
* }
|
|
3994
|
-
*/
|
|
3995
|
-
class CredentialEntity {
|
|
3996
|
-
/**
|
|
3997
|
-
* Generate Account Id key component as per the schema: <home_account_id>-<environment>
|
|
3998
|
-
*/
|
|
3999
|
-
generateAccountId() {
|
|
4000
|
-
return CredentialEntity.generateAccountIdForCacheKey(this.homeAccountId, this.environment);
|
|
4001
|
-
}
|
|
4002
|
-
/**
|
|
4003
|
-
* Generate Credential Id key component as per the schema: <credential_type>-<client_id>-<realm>
|
|
4004
|
-
*/
|
|
4005
|
-
generateCredentialId() {
|
|
4006
|
-
return CredentialEntity.generateCredentialIdForCacheKey(this.credentialType, this.clientId, this.realm, this.familyId);
|
|
4007
|
-
}
|
|
4008
|
-
/**
|
|
4009
|
-
* Generate target key component as per schema: <target>
|
|
4010
|
-
*/
|
|
4011
|
-
generateTarget() {
|
|
4012
|
-
return CredentialEntity.generateTargetForCacheKey(this.target);
|
|
4013
|
-
}
|
|
4014
|
-
/**
|
|
4015
|
-
* generates credential key
|
|
4016
|
-
*/
|
|
4017
|
-
generateCredentialKey() {
|
|
4018
|
-
return CredentialEntity.generateCredentialCacheKey(this.homeAccountId, this.environment, this.credentialType, this.clientId, this.realm, this.target, this.familyId, this.tokenType, this.requestedClaimsHash);
|
|
4019
|
-
}
|
|
4020
|
-
/**
|
|
4021
|
-
* returns the type of the cache (in this case credential)
|
|
4022
|
-
*/
|
|
4023
|
-
generateType() {
|
|
4024
|
-
switch (this.credentialType) {
|
|
4025
|
-
case CredentialType.ID_TOKEN:
|
|
4026
|
-
return CacheType.ID_TOKEN;
|
|
4027
|
-
case CredentialType.ACCESS_TOKEN:
|
|
4028
|
-
case CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME:
|
|
4029
|
-
return CacheType.ACCESS_TOKEN;
|
|
4030
|
-
case CredentialType.REFRESH_TOKEN:
|
|
4031
|
-
return CacheType.REFRESH_TOKEN;
|
|
4032
|
-
default: {
|
|
4033
|
-
throw ClientAuthError.createUnexpectedCredentialTypeError();
|
|
4034
|
-
}
|
|
4035
|
-
}
|
|
4036
|
-
}
|
|
4037
|
-
/**
|
|
4038
|
-
* generates credential key
|
|
4039
|
-
* <home_account_id*>-\<environment>-<credential_type>-<client_id>-<realm\*>-<target\*>-<scheme\*>
|
|
4040
|
-
*/
|
|
4041
|
-
static generateCredentialCacheKey(homeAccountId, environment, credentialType, clientId, realm, target, familyId, tokenType, requestedClaimsHash) {
|
|
4042
|
-
const credentialKey = [
|
|
4043
|
-
this.generateAccountIdForCacheKey(homeAccountId, environment),
|
|
4044
|
-
this.generateCredentialIdForCacheKey(credentialType, clientId, realm, familyId),
|
|
4045
|
-
this.generateTargetForCacheKey(target),
|
|
4046
|
-
this.generateClaimsHashForCacheKey(requestedClaimsHash),
|
|
4047
|
-
this.generateSchemeForCacheKey(tokenType),
|
|
4048
|
-
];
|
|
4049
|
-
return credentialKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
|
4050
|
-
}
|
|
4051
|
-
/**
|
|
4052
|
-
* generates Account Id for keys
|
|
4053
|
-
* @param homeAccountId
|
|
4054
|
-
* @param environment
|
|
4055
|
-
*/
|
|
4056
|
-
static generateAccountIdForCacheKey(homeAccountId, environment) {
|
|
4057
|
-
const accountId = [homeAccountId, environment];
|
|
4058
|
-
return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
|
4059
|
-
}
|
|
4060
|
-
/**
|
|
4061
|
-
* Generates Credential Id for keys
|
|
4062
|
-
* @param credentialType
|
|
4063
|
-
* @param realm
|
|
4064
|
-
* @param clientId
|
|
4065
|
-
* @param familyId
|
|
4066
|
-
*/
|
|
4067
|
-
static generateCredentialIdForCacheKey(credentialType, clientId, realm, familyId) {
|
|
4068
|
-
const clientOrFamilyId = credentialType === CredentialType.REFRESH_TOKEN
|
|
4069
|
-
? familyId || clientId
|
|
4070
|
-
: clientId;
|
|
4071
|
-
const credentialId = [
|
|
4072
|
-
credentialType,
|
|
4073
|
-
clientOrFamilyId,
|
|
4074
|
-
realm || Constants.EMPTY_STRING,
|
|
4075
|
-
];
|
|
4076
|
-
return credentialId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
|
4077
|
-
}
|
|
4078
|
-
/**
|
|
4079
|
-
* Generate target key component as per schema: <target>
|
|
4080
|
-
*/
|
|
4081
|
-
static generateTargetForCacheKey(scopes) {
|
|
4082
|
-
return (scopes || Constants.EMPTY_STRING).toLowerCase();
|
|
4083
|
-
}
|
|
4084
|
-
/**
|
|
4085
|
-
* Generate requested claims key component as per schema: <requestedClaims>
|
|
4086
|
-
*/
|
|
4087
|
-
static generateClaimsHashForCacheKey(requestedClaimsHash) {
|
|
4088
|
-
return (requestedClaimsHash || Constants.EMPTY_STRING).toLowerCase();
|
|
4089
|
-
}
|
|
4090
|
-
/**
|
|
4091
|
-
* Generate scheme key componenet as per schema: <scheme>
|
|
4092
|
-
*/
|
|
4093
|
-
static generateSchemeForCacheKey(tokenType) {
|
|
4094
|
-
/*
|
|
4095
|
-
* PoP Tokens and SSH certs include scheme in cache key
|
|
4096
|
-
* Cast to lowercase to handle "bearer" from ADFS
|
|
4097
|
-
*/
|
|
4098
|
-
return tokenType &&
|
|
4099
|
-
tokenType.toLowerCase() !==
|
|
4100
|
-
AuthenticationScheme.BEARER.toLowerCase()
|
|
4101
|
-
? tokenType.toLowerCase()
|
|
4102
|
-
: Constants.EMPTY_STRING;
|
|
4103
|
-
}
|
|
4104
|
-
}
|
|
4105
|
-
|
|
4106
|
-
/*
|
|
4107
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4108
|
-
* Licensed under the MIT License.
|
|
4109
|
-
*/
|
|
4110
|
-
/**
|
|
4111
|
-
* ID_TOKEN Cache
|
|
4112
|
-
*
|
|
4113
|
-
* Key:Value Schema:
|
|
4114
|
-
*
|
|
4115
|
-
* Key Example: uid.utid-login.microsoftonline.com-idtoken-clientId-contoso.com-
|
|
4116
|
-
*
|
|
4117
|
-
* Value Schema:
|
|
4118
|
-
* {
|
|
4119
|
-
* homeAccountId: home account identifier for the auth scheme,
|
|
4120
|
-
* environment: entity that issued the token, represented as a full host
|
|
4121
|
-
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
|
4122
|
-
* clientId: client ID of the application
|
|
4123
|
-
* secret: Actual credential as a string
|
|
4124
|
-
* realm: Full tenant or organizational identifier that the account belongs to
|
|
4125
|
-
* }
|
|
4126
|
-
*/
|
|
4127
|
-
class IdTokenEntity extends CredentialEntity {
|
|
4128
|
-
/**
|
|
4129
|
-
* Create IdTokenEntity
|
|
4130
|
-
* @param homeAccountId
|
|
4131
|
-
* @param authenticationResult
|
|
4132
|
-
* @param clientId
|
|
4133
|
-
* @param authority
|
|
4134
|
-
*/
|
|
4135
|
-
static createIdTokenEntity(homeAccountId, environment, idToken, clientId, tenantId) {
|
|
4136
|
-
const idTokenEntity = new IdTokenEntity();
|
|
4137
|
-
idTokenEntity.credentialType = CredentialType.ID_TOKEN;
|
|
4138
|
-
idTokenEntity.homeAccountId = homeAccountId;
|
|
4139
|
-
idTokenEntity.environment = environment;
|
|
4140
|
-
idTokenEntity.clientId = clientId;
|
|
4141
|
-
idTokenEntity.secret = idToken;
|
|
4142
|
-
idTokenEntity.realm = tenantId;
|
|
4143
|
-
return idTokenEntity;
|
|
4144
|
-
}
|
|
4145
|
-
/**
|
|
4146
|
-
* Validates an entity: checks for all expected params
|
|
4147
|
-
* @param entity
|
|
4148
|
-
*/
|
|
4149
|
-
static isIdTokenEntity(entity) {
|
|
4150
|
-
if (!entity) {
|
|
4151
|
-
return false;
|
|
4152
|
-
}
|
|
4153
|
-
return (entity.hasOwnProperty("homeAccountId") &&
|
|
4154
|
-
entity.hasOwnProperty("environment") &&
|
|
4155
|
-
entity.hasOwnProperty("credentialType") &&
|
|
4156
|
-
entity.hasOwnProperty("realm") &&
|
|
4157
|
-
entity.hasOwnProperty("clientId") &&
|
|
4158
|
-
entity.hasOwnProperty("secret") &&
|
|
4159
|
-
entity["credentialType"] === CredentialType.ID_TOKEN);
|
|
4160
|
-
}
|
|
4161
|
-
}
|
|
4162
|
-
|
|
4163
|
-
/*
|
|
4164
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4165
|
-
* Licensed under the MIT License.
|
|
4166
|
-
*/
|
|
4167
|
-
/**
|
|
4168
|
-
* Utility class which exposes functions for managing date and time operations.
|
|
4169
|
-
*/
|
|
4170
|
-
class TimeUtils {
|
|
4171
|
-
/**
|
|
4172
|
-
* return the current time in Unix time (seconds).
|
|
4173
|
-
*/
|
|
4174
|
-
static nowSeconds() {
|
|
4175
|
-
// Date.getTime() returns in milliseconds.
|
|
4176
|
-
return Math.round(new Date().getTime() / 1000.0);
|
|
4177
|
-
}
|
|
4178
|
-
/**
|
|
4179
|
-
* check if a token is expired based on given UTC time in seconds.
|
|
4180
|
-
* @param expiresOn
|
|
4181
|
-
*/
|
|
4182
|
-
static isTokenExpired(expiresOn, offset) {
|
|
4183
|
-
// check for access token expiry
|
|
4184
|
-
const expirationSec = Number(expiresOn) || 0;
|
|
4185
|
-
const offsetCurrentTimeSec = TimeUtils.nowSeconds() + offset;
|
|
4186
|
-
// If current time + offset is greater than token expiration time, then token is expired.
|
|
4187
|
-
return offsetCurrentTimeSec > expirationSec;
|
|
4188
|
-
}
|
|
4189
|
-
/**
|
|
4190
|
-
* If the current time is earlier than the time that a token was cached at, we must discard the token
|
|
4191
|
-
* i.e. The system clock was turned back after acquiring the cached token
|
|
4192
|
-
* @param cachedAt
|
|
4193
|
-
* @param offset
|
|
4194
|
-
*/
|
|
4195
|
-
static wasClockTurnedBack(cachedAt) {
|
|
4196
|
-
const cachedAtSec = Number(cachedAt);
|
|
4197
|
-
return cachedAtSec > TimeUtils.nowSeconds();
|
|
4198
|
-
}
|
|
4199
|
-
/**
|
|
4200
|
-
* Waits for t number of milliseconds
|
|
4201
|
-
* @param t number
|
|
4202
|
-
* @param value T
|
|
4203
|
-
*/
|
|
4204
|
-
static delay(t, value) {
|
|
4205
|
-
return new Promise((resolve) => setTimeout(() => resolve(value), t));
|
|
4206
|
-
}
|
|
4207
|
-
}
|
|
4208
|
-
|
|
4209
|
-
/*
|
|
4210
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4211
|
-
* Licensed under the MIT License.
|
|
4212
|
-
*/
|
|
4213
|
-
/**
|
|
4214
|
-
* ACCESS_TOKEN Credential Type
|
|
4215
|
-
*
|
|
4216
|
-
* Key:Value Schema:
|
|
4217
|
-
*
|
|
4218
|
-
* Key Example: uid.utid-login.microsoftonline.com-accesstoken-clientId-contoso.com-user.read
|
|
4219
|
-
*
|
|
4220
|
-
* Value Schema:
|
|
4221
|
-
* {
|
|
4222
|
-
* homeAccountId: home account identifier for the auth scheme,
|
|
4223
|
-
* environment: entity that issued the token, represented as a full host
|
|
4224
|
-
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
|
4225
|
-
* clientId: client ID of the application
|
|
4226
|
-
* secret: Actual credential as a string
|
|
4227
|
-
* familyId: Family ID identifier, usually only used for refresh tokens
|
|
4228
|
-
* realm: Full tenant or organizational identifier that the account belongs to
|
|
4229
|
-
* target: Permissions that are included in the token, or for refresh tokens, the resource identifier.
|
|
4230
|
-
* cachedAt: Absolute device time when entry was created in the cache.
|
|
4231
|
-
* expiresOn: Token expiry time, calculated based on current UTC time in seconds. Represented as a string.
|
|
4232
|
-
* extendedExpiresOn: Additional extended expiry time until when token is valid in case of server-side outage. Represented as string in UTC seconds.
|
|
4233
|
-
* keyId: used for POP and SSH tokenTypes
|
|
4234
|
-
* tokenType: Type of the token issued. Usually "Bearer"
|
|
4235
|
-
* }
|
|
4236
|
-
*/
|
|
4237
|
-
class AccessTokenEntity extends CredentialEntity {
|
|
4238
|
-
/**
|
|
4239
|
-
* Create AccessTokenEntity
|
|
4240
|
-
* @param homeAccountId
|
|
4241
|
-
* @param environment
|
|
4242
|
-
* @param accessToken
|
|
4243
|
-
* @param clientId
|
|
4244
|
-
* @param tenantId
|
|
4245
|
-
* @param scopes
|
|
4246
|
-
* @param expiresOn
|
|
4247
|
-
* @param extExpiresOn
|
|
4248
|
-
*/
|
|
4249
|
-
static createAccessTokenEntity(homeAccountId, environment, accessToken, clientId, tenantId, scopes, expiresOn, extExpiresOn, cryptoUtils, refreshOn, tokenType, userAssertionHash, keyId, requestedClaims, requestedClaimsHash) {
|
|
4250
|
-
const atEntity = new AccessTokenEntity();
|
|
4251
|
-
atEntity.homeAccountId = homeAccountId;
|
|
4252
|
-
atEntity.credentialType = CredentialType.ACCESS_TOKEN;
|
|
4253
|
-
atEntity.secret = accessToken;
|
|
4254
|
-
const currentTime = TimeUtils.nowSeconds();
|
|
4255
|
-
atEntity.cachedAt = currentTime.toString();
|
|
4256
|
-
/*
|
|
4257
|
-
* Token expiry time.
|
|
4258
|
-
* This value should be calculated based on the current UTC time measured locally and the value expires_in Represented as a string in JSON.
|
|
4259
|
-
*/
|
|
4260
|
-
atEntity.expiresOn = expiresOn.toString();
|
|
4261
|
-
atEntity.extendedExpiresOn = extExpiresOn.toString();
|
|
4262
|
-
if (refreshOn) {
|
|
4263
|
-
atEntity.refreshOn = refreshOn.toString();
|
|
4264
|
-
}
|
|
4265
|
-
atEntity.environment = environment;
|
|
4266
|
-
atEntity.clientId = clientId;
|
|
4267
|
-
atEntity.realm = tenantId;
|
|
4268
|
-
atEntity.target = scopes;
|
|
4269
|
-
atEntity.userAssertionHash = userAssertionHash;
|
|
4270
|
-
atEntity.tokenType = StringUtils.isEmpty(tokenType)
|
|
4271
|
-
? AuthenticationScheme.BEARER
|
|
4272
|
-
: tokenType;
|
|
4273
|
-
if (requestedClaims) {
|
|
4274
|
-
atEntity.requestedClaims = requestedClaims;
|
|
4275
|
-
atEntity.requestedClaimsHash = requestedClaimsHash;
|
|
4276
|
-
}
|
|
4277
|
-
/*
|
|
4278
|
-
* Create Access Token With Auth Scheme instead of regular access token
|
|
4279
|
-
* Cast to lower to handle "bearer" from ADFS
|
|
4280
|
-
*/
|
|
4281
|
-
if (atEntity.tokenType?.toLowerCase() !==
|
|
4282
|
-
AuthenticationScheme.BEARER.toLowerCase()) {
|
|
4283
|
-
atEntity.credentialType =
|
|
4284
|
-
CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;
|
|
4285
|
-
switch (atEntity.tokenType) {
|
|
4286
|
-
case AuthenticationScheme.POP:
|
|
4287
|
-
// Make sure keyId is present and add it to credential
|
|
4288
|
-
const tokenClaims = AuthToken.extractTokenClaims(accessToken, cryptoUtils);
|
|
4289
|
-
if (!tokenClaims?.cnf?.kid) {
|
|
4290
|
-
throw ClientAuthError.createTokenClaimsRequiredError();
|
|
4291
|
-
}
|
|
4292
|
-
atEntity.keyId = tokenClaims.cnf.kid;
|
|
4293
|
-
break;
|
|
4294
|
-
case AuthenticationScheme.SSH:
|
|
4295
|
-
atEntity.keyId = keyId;
|
|
4296
|
-
}
|
|
4297
|
-
}
|
|
4298
|
-
return atEntity;
|
|
4299
|
-
}
|
|
4300
|
-
/**
|
|
4301
|
-
* Validates an entity: checks for all expected params
|
|
4302
|
-
* @param entity
|
|
4303
|
-
*/
|
|
4304
|
-
static isAccessTokenEntity(entity) {
|
|
4305
|
-
if (!entity) {
|
|
4306
|
-
return false;
|
|
4307
|
-
}
|
|
4308
|
-
return (entity.hasOwnProperty("homeAccountId") &&
|
|
4309
|
-
entity.hasOwnProperty("environment") &&
|
|
4310
|
-
entity.hasOwnProperty("credentialType") &&
|
|
4311
|
-
entity.hasOwnProperty("realm") &&
|
|
4312
|
-
entity.hasOwnProperty("clientId") &&
|
|
4313
|
-
entity.hasOwnProperty("secret") &&
|
|
4314
|
-
entity.hasOwnProperty("target") &&
|
|
4315
|
-
(entity["credentialType"] === CredentialType.ACCESS_TOKEN ||
|
|
4316
|
-
entity["credentialType"] ===
|
|
4317
|
-
CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME));
|
|
4318
|
-
}
|
|
4319
|
-
}
|
|
4320
|
-
|
|
4321
|
-
/*
|
|
4322
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4323
|
-
* Licensed under the MIT License.
|
|
4324
|
-
*/
|
|
4325
|
-
/**
|
|
4326
|
-
* REFRESH_TOKEN Cache
|
|
4327
|
-
*
|
|
4328
|
-
* Key:Value Schema:
|
|
4329
|
-
*
|
|
4330
|
-
* Key Example: uid.utid-login.microsoftonline.com-refreshtoken-clientId--
|
|
4331
|
-
*
|
|
4332
|
-
* Value:
|
|
4333
|
-
* {
|
|
4334
|
-
* homeAccountId: home account identifier for the auth scheme,
|
|
4335
|
-
* environment: entity that issued the token, represented as a full host
|
|
4336
|
-
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
|
4337
|
-
* clientId: client ID of the application
|
|
4338
|
-
* secret: Actual credential as a string
|
|
4339
|
-
* familyId: Family ID identifier, '1' represents Microsoft Family
|
|
4340
|
-
* realm: Full tenant or organizational identifier that the account belongs to
|
|
4341
|
-
* target: Permissions that are included in the token, or for refresh tokens, the resource identifier.
|
|
4342
|
-
* }
|
|
4343
|
-
*/
|
|
4344
|
-
class RefreshTokenEntity extends CredentialEntity {
|
|
4345
|
-
/**
|
|
4346
|
-
* Create RefreshTokenEntity
|
|
4347
|
-
* @param homeAccountId
|
|
4348
|
-
* @param authenticationResult
|
|
4349
|
-
* @param clientId
|
|
4350
|
-
* @param authority
|
|
4351
|
-
*/
|
|
4352
|
-
static createRefreshTokenEntity(homeAccountId, environment, refreshToken, clientId, familyId, userAssertionHash) {
|
|
4353
|
-
const rtEntity = new RefreshTokenEntity();
|
|
4354
|
-
rtEntity.clientId = clientId;
|
|
4355
|
-
rtEntity.credentialType = CredentialType.REFRESH_TOKEN;
|
|
4356
|
-
rtEntity.environment = environment;
|
|
4357
|
-
rtEntity.homeAccountId = homeAccountId;
|
|
4358
|
-
rtEntity.secret = refreshToken;
|
|
4359
|
-
rtEntity.userAssertionHash = userAssertionHash;
|
|
4360
|
-
if (familyId)
|
|
4361
|
-
rtEntity.familyId = familyId;
|
|
4362
|
-
return rtEntity;
|
|
4363
|
-
}
|
|
4364
|
-
/**
|
|
4365
|
-
* Validates an entity: checks for all expected params
|
|
4366
|
-
* @param entity
|
|
4367
|
-
*/
|
|
4368
|
-
static isRefreshTokenEntity(entity) {
|
|
4369
|
-
if (!entity) {
|
|
4370
|
-
return false;
|
|
4371
|
-
}
|
|
4372
|
-
return (entity.hasOwnProperty("homeAccountId") &&
|
|
4373
|
-
entity.hasOwnProperty("environment") &&
|
|
4374
|
-
entity.hasOwnProperty("credentialType") &&
|
|
4375
|
-
entity.hasOwnProperty("clientId") &&
|
|
4376
|
-
entity.hasOwnProperty("secret") &&
|
|
4377
|
-
entity["credentialType"] === CredentialType.REFRESH_TOKEN);
|
|
4378
|
-
}
|
|
4379
|
-
}
|
|
4380
|
-
|
|
4381
|
-
/*
|
|
4382
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4383
|
-
* Licensed under the MIT License.
|
|
4384
|
-
*/
|
|
4385
|
-
/**
|
|
4386
|
-
* InteractionRequiredServerErrorMessage contains string constants used by error codes and messages returned by the server indicating interaction is required
|
|
4387
|
-
*/
|
|
4388
|
-
const InteractionRequiredServerErrorMessage = [
|
|
4389
|
-
"interaction_required",
|
|
4390
|
-
"consent_required",
|
|
4391
|
-
"login_required",
|
|
4392
|
-
];
|
|
4393
|
-
const InteractionRequiredAuthSubErrorMessage = [
|
|
4394
|
-
"message_only",
|
|
4395
|
-
"additional_action",
|
|
4396
|
-
"basic_action",
|
|
4397
|
-
"user_password_expired",
|
|
4398
|
-
"consent_required",
|
|
4399
|
-
];
|
|
4400
|
-
/**
|
|
4401
|
-
* Interaction required errors defined by the SDK
|
|
4402
|
-
*/
|
|
4403
|
-
const InteractionRequiredAuthErrorMessage = {
|
|
4404
|
-
noTokensFoundError: {
|
|
4405
|
-
code: "no_tokens_found",
|
|
4406
|
-
desc: "No refresh token found in the cache. Please sign-in.",
|
|
4407
|
-
},
|
|
4408
|
-
native_account_unavailable: {
|
|
4409
|
-
code: "native_account_unavailable",
|
|
4410
|
-
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.",
|
|
4411
|
-
},
|
|
4412
|
-
};
|
|
4413
|
-
/**
|
|
4414
|
-
* Error thrown when user interaction is required.
|
|
4415
|
-
*/
|
|
4416
|
-
class InteractionRequiredAuthError extends AuthError {
|
|
4417
|
-
constructor(errorCode, errorMessage, subError, timestamp, traceId, correlationId, claims) {
|
|
4418
|
-
super(errorCode, errorMessage, subError);
|
|
4419
|
-
Object.setPrototypeOf(this, InteractionRequiredAuthError.prototype);
|
|
4420
|
-
this.timestamp = timestamp || Constants.EMPTY_STRING;
|
|
4421
|
-
this.traceId = traceId || Constants.EMPTY_STRING;
|
|
4422
|
-
this.correlationId = correlationId || Constants.EMPTY_STRING;
|
|
4423
|
-
this.claims = claims || Constants.EMPTY_STRING;
|
|
4424
|
-
this.name = "InteractionRequiredAuthError";
|
|
4425
|
-
}
|
|
4426
|
-
/**
|
|
4427
|
-
* Helper function used to determine if an error thrown by the server requires interaction to resolve
|
|
4428
|
-
* @param errorCode
|
|
4429
|
-
* @param errorString
|
|
4430
|
-
* @param subError
|
|
4431
|
-
*/
|
|
4432
|
-
static isInteractionRequiredError(errorCode, errorString, subError) {
|
|
4433
|
-
const isInteractionRequiredErrorCode = !!errorCode &&
|
|
4434
|
-
InteractionRequiredServerErrorMessage.indexOf(errorCode) > -1;
|
|
4435
|
-
const isInteractionRequiredSubError = !!subError &&
|
|
4436
|
-
InteractionRequiredAuthSubErrorMessage.indexOf(subError) > -1;
|
|
4437
|
-
const isInteractionRequiredErrorDesc = !!errorString &&
|
|
4438
|
-
InteractionRequiredServerErrorMessage.some((irErrorCode) => {
|
|
4439
|
-
return errorString.indexOf(irErrorCode) > -1;
|
|
4440
|
-
});
|
|
4441
|
-
return (isInteractionRequiredErrorCode ||
|
|
4442
|
-
isInteractionRequiredErrorDesc ||
|
|
4443
|
-
isInteractionRequiredSubError);
|
|
4444
|
-
}
|
|
4445
|
-
/**
|
|
4446
|
-
* Creates an error thrown when the authorization code required for a token request is null or empty.
|
|
4447
|
-
*/
|
|
4448
|
-
static createNoTokensFoundError() {
|
|
4449
|
-
return new InteractionRequiredAuthError(InteractionRequiredAuthErrorMessage.noTokensFoundError.code, InteractionRequiredAuthErrorMessage.noTokensFoundError.desc);
|
|
4450
|
-
}
|
|
4451
|
-
/**
|
|
4452
|
-
* Creates an error thrown when the native broker returns ACCOUNT_UNAVAILABLE status, indicating that the account was removed and interactive sign-in is required
|
|
4453
|
-
* @returns
|
|
4454
|
-
*/
|
|
4455
|
-
static createNativeAccountUnavailableError() {
|
|
4456
|
-
return new InteractionRequiredAuthError(InteractionRequiredAuthErrorMessage.native_account_unavailable.code, InteractionRequiredAuthErrorMessage.native_account_unavailable.desc);
|
|
4457
|
-
}
|
|
4458
|
-
}
|
|
4459
|
-
|
|
4460
|
-
/*
|
|
4461
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4462
|
-
* Licensed under the MIT License.
|
|
4463
|
-
*/
|
|
4464
|
-
class CacheRecord {
|
|
4465
|
-
constructor(accountEntity, idTokenEntity, accessTokenEntity, refreshTokenEntity, appMetadataEntity) {
|
|
4466
|
-
this.account = accountEntity || null;
|
|
4467
|
-
this.idToken = idTokenEntity || null;
|
|
4468
|
-
this.accessToken = accessTokenEntity || null;
|
|
4469
|
-
this.refreshToken = refreshTokenEntity || null;
|
|
4470
|
-
this.appMetadata = appMetadataEntity || null;
|
|
4471
|
-
}
|
|
4472
|
-
}
|
|
4473
|
-
|
|
4474
|
-
/*
|
|
4475
|
-
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4476
|
-
* Licensed under the MIT License.
|
|
4477
|
-
*/
|
|
4478
|
-
/**
|
|
4479
|
-
* Class which provides helpers for OAuth 2.0 protocol specific values
|
|
4480
|
-
*/
|
|
4481
|
-
class ProtocolUtils {
|
|
4154
|
+
}
|
|
4155
|
+
return headers;
|
|
4156
|
+
}
|
|
4482
4157
|
/**
|
|
4483
|
-
*
|
|
4484
|
-
* @param
|
|
4485
|
-
* @param
|
|
4158
|
+
* Http post to token endpoint
|
|
4159
|
+
* @param tokenEndpoint
|
|
4160
|
+
* @param queryString
|
|
4161
|
+
* @param headers
|
|
4162
|
+
* @param thumbprint
|
|
4486
4163
|
*/
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
:
|
|
4164
|
+
async executePostToTokenEndpoint(tokenEndpoint, queryString, headers, thumbprint, correlationId) {
|
|
4165
|
+
this.performanceClient?.addQueueMeasurement(PerformanceEvents.BaseClientCreateTokenRequestHeaders, correlationId);
|
|
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);
|
|
4171
|
+
if (this.config.serverTelemetryManager &&
|
|
4172
|
+
response.status < 500 &&
|
|
4173
|
+
response.status !== 429) {
|
|
4174
|
+
// Telemetry data successfully logged by server, clear Telemetry cache
|
|
4175
|
+
this.config.serverTelemetryManager.clearTelemetryCache();
|
|
4176
|
+
}
|
|
4177
|
+
return response;
|
|
4492
4178
|
}
|
|
4493
4179
|
/**
|
|
4494
|
-
*
|
|
4495
|
-
* @param
|
|
4496
|
-
* @param cryptoObj
|
|
4180
|
+
* Updates the authority object of the client. Endpoint discovery must be completed.
|
|
4181
|
+
* @param updatedAuthority
|
|
4497
4182
|
*/
|
|
4498
|
-
|
|
4499
|
-
if (!
|
|
4500
|
-
throw ClientAuthError.
|
|
4501
|
-
}
|
|
4502
|
-
// Create a state object containing a unique id and the timestamp of the request creation
|
|
4503
|
-
const stateObj = {
|
|
4504
|
-
id: cryptoObj.createNewGuid(),
|
|
4505
|
-
};
|
|
4506
|
-
if (meta) {
|
|
4507
|
-
stateObj.meta = meta;
|
|
4183
|
+
updateAuthority(updatedAuthority) {
|
|
4184
|
+
if (!updatedAuthority.discoveryComplete()) {
|
|
4185
|
+
throw ClientAuthError.createEndpointDiscoveryIncompleteError("Updated authority has not completed endpoint discovery.");
|
|
4508
4186
|
}
|
|
4509
|
-
|
|
4510
|
-
return cryptoObj.base64Encode(stateString);
|
|
4187
|
+
this.authority = updatedAuthority;
|
|
4511
4188
|
}
|
|
4512
4189
|
/**
|
|
4513
|
-
*
|
|
4514
|
-
* @param
|
|
4515
|
-
* @param cryptoObj
|
|
4190
|
+
* Creates query string for the /token request
|
|
4191
|
+
* @param request
|
|
4516
4192
|
*/
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
if (StringUtils.isEmpty(state)) {
|
|
4522
|
-
throw ClientAuthError.createInvalidStateError(state, "Null, undefined or empty state");
|
|
4523
|
-
}
|
|
4524
|
-
try {
|
|
4525
|
-
// Split the state between library state and user passed state and decode them separately
|
|
4526
|
-
const splitState = state.split(Constants.RESOURCE_DELIM);
|
|
4527
|
-
const libraryState = splitState[0];
|
|
4528
|
-
const userState = splitState.length > 1
|
|
4529
|
-
? splitState.slice(1).join(Constants.RESOURCE_DELIM)
|
|
4530
|
-
: Constants.EMPTY_STRING;
|
|
4531
|
-
const libraryStateString = cryptoObj.base64Decode(libraryState);
|
|
4532
|
-
const libraryStateObj = JSON.parse(libraryStateString);
|
|
4533
|
-
return {
|
|
4534
|
-
userRequestState: !StringUtils.isEmpty(userState)
|
|
4535
|
-
? userState
|
|
4536
|
-
: Constants.EMPTY_STRING,
|
|
4537
|
-
libraryState: libraryStateObj,
|
|
4538
|
-
};
|
|
4539
|
-
}
|
|
4540
|
-
catch (e) {
|
|
4541
|
-
throw ClientAuthError.createInvalidStateError(state, e);
|
|
4193
|
+
createTokenQueryParameters(request) {
|
|
4194
|
+
const parameterBuilder = new RequestParameterBuilder();
|
|
4195
|
+
if (request.tokenQueryParameters) {
|
|
4196
|
+
parameterBuilder.addExtraQueryParameters(request.tokenQueryParameters);
|
|
4542
4197
|
}
|
|
4198
|
+
return parameterBuilder.createQueryString();
|
|
4543
4199
|
}
|
|
4544
4200
|
}
|
|
4545
4201
|
|
|
@@ -4548,280 +4204,408 @@ class ProtocolUtils {
|
|
|
4548
4204
|
* Licensed under the MIT License.
|
|
4549
4205
|
*/
|
|
4550
4206
|
/**
|
|
4551
|
-
*
|
|
4207
|
+
* Base type for credentials to be stored in the cache: eg: ACCESS_TOKEN, ID_TOKEN etc
|
|
4208
|
+
*
|
|
4209
|
+
* Key:Value Schema:
|
|
4210
|
+
*
|
|
4211
|
+
* Key: <home_account_id*>-<environment>-<credential_type>-<client_id>-<realm*>-<target*>-<requestedClaims*>-<scheme*>
|
|
4212
|
+
*
|
|
4213
|
+
* Value Schema:
|
|
4214
|
+
* {
|
|
4215
|
+
* homeAccountId: home account identifier for the auth scheme,
|
|
4216
|
+
* environment: entity that issued the token, represented as a full host
|
|
4217
|
+
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
|
4218
|
+
* clientId: client ID of the application
|
|
4219
|
+
* secret: Actual credential as a string
|
|
4220
|
+
* familyId: Family ID identifier, usually only used for refresh tokens
|
|
4221
|
+
* realm: Full tenant or organizational identifier that the account belongs to
|
|
4222
|
+
* target: Permissions that are included in the token, or for refresh tokens, the resource identifier.
|
|
4223
|
+
* tokenType: Matches the authentication scheme for which the token was issued (i.e. Bearer or pop)
|
|
4224
|
+
* requestedClaimsHash: Matches the SHA 256 hash of the claims object included in the token request
|
|
4225
|
+
* userAssertionHash: Matches the SHA 256 hash of the obo_assertion for the OBO flow
|
|
4226
|
+
* }
|
|
4552
4227
|
*/
|
|
4553
|
-
class
|
|
4554
|
-
|
|
4555
|
-
|
|
4228
|
+
class CredentialEntity {
|
|
4229
|
+
/**
|
|
4230
|
+
* Generate Account Id key component as per the schema: <home_account_id>-<environment>
|
|
4231
|
+
*/
|
|
4232
|
+
generateAccountId() {
|
|
4233
|
+
return CredentialEntity.generateAccountIdForCacheKey(this.homeAccountId, this.environment);
|
|
4556
4234
|
}
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
}
|
|
4563
|
-
if (StringUtils.isEmpty(this.getHash())) {
|
|
4564
|
-
this._urlString = UrlString.canonicalizeUri(url);
|
|
4565
|
-
}
|
|
4235
|
+
/**
|
|
4236
|
+
* Generate Credential Id key component as per the schema: <credential_type>-<client_id>-<realm>
|
|
4237
|
+
*/
|
|
4238
|
+
generateCredentialId() {
|
|
4239
|
+
return CredentialEntity.generateCredentialIdForCacheKey(this.credentialType, this.clientId, this.realm, this.familyId);
|
|
4566
4240
|
}
|
|
4567
4241
|
/**
|
|
4568
|
-
*
|
|
4569
|
-
* @param url
|
|
4242
|
+
* Generate target key component as per schema: <target>
|
|
4570
4243
|
*/
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4574
|
-
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4244
|
+
generateTarget() {
|
|
4245
|
+
return CredentialEntity.generateTargetForCacheKey(this.target);
|
|
4246
|
+
}
|
|
4247
|
+
/**
|
|
4248
|
+
* generates credential key
|
|
4249
|
+
*/
|
|
4250
|
+
generateCredentialKey() {
|
|
4251
|
+
return CredentialEntity.generateCredentialCacheKey(this.homeAccountId, this.environment, this.credentialType, this.clientId, this.realm, this.target, this.familyId, this.tokenType, this.requestedClaimsHash);
|
|
4252
|
+
}
|
|
4253
|
+
/**
|
|
4254
|
+
* returns the type of the cache (in this case credential)
|
|
4255
|
+
*/
|
|
4256
|
+
generateType() {
|
|
4257
|
+
switch (this.credentialType) {
|
|
4258
|
+
case CredentialType.ID_TOKEN:
|
|
4259
|
+
return CacheType.ID_TOKEN;
|
|
4260
|
+
case CredentialType.ACCESS_TOKEN:
|
|
4261
|
+
case CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME:
|
|
4262
|
+
return CacheType.ACCESS_TOKEN;
|
|
4263
|
+
case CredentialType.REFRESH_TOKEN:
|
|
4264
|
+
return CacheType.REFRESH_TOKEN;
|
|
4265
|
+
default: {
|
|
4266
|
+
throw ClientAuthError.createUnexpectedCredentialTypeError();
|
|
4582
4267
|
}
|
|
4583
|
-
return lowerCaseUrl;
|
|
4584
4268
|
}
|
|
4585
|
-
return url;
|
|
4586
4269
|
}
|
|
4587
4270
|
/**
|
|
4588
|
-
*
|
|
4271
|
+
* generates credential key
|
|
4272
|
+
* <home_account_id*>-\<environment>-<credential_type>-<client_id>-<realm\*>-<target\*>-<scheme\*>
|
|
4589
4273
|
*/
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4595
|
-
|
|
4596
|
-
|
|
4597
|
-
|
|
4598
|
-
|
|
4599
|
-
// Throw error if URI or path segments are not parseable.
|
|
4600
|
-
if (!components.HostNameAndPort || !components.PathSegments) {
|
|
4601
|
-
throw ClientConfigurationError.createUrlParseError(`Given url string: ${this.urlString}`);
|
|
4602
|
-
}
|
|
4603
|
-
// Throw error if uri is insecure.
|
|
4604
|
-
if (!components.Protocol ||
|
|
4605
|
-
components.Protocol.toLowerCase() !== "https:") {
|
|
4606
|
-
throw ClientConfigurationError.createInsecureAuthorityUriError(this.urlString);
|
|
4607
|
-
}
|
|
4274
|
+
static generateCredentialCacheKey(homeAccountId, environment, credentialType, clientId, realm, target, familyId, tokenType, requestedClaimsHash) {
|
|
4275
|
+
const credentialKey = [
|
|
4276
|
+
this.generateAccountIdForCacheKey(homeAccountId, environment),
|
|
4277
|
+
this.generateCredentialIdForCacheKey(credentialType, clientId, realm, familyId),
|
|
4278
|
+
this.generateTargetForCacheKey(target),
|
|
4279
|
+
this.generateClaimsHashForCacheKey(requestedClaimsHash),
|
|
4280
|
+
this.generateSchemeForCacheKey(tokenType),
|
|
4281
|
+
];
|
|
4282
|
+
return credentialKey.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
|
4608
4283
|
}
|
|
4609
4284
|
/**
|
|
4610
|
-
*
|
|
4611
|
-
* @param
|
|
4612
|
-
* @param
|
|
4285
|
+
* generates Account Id for keys
|
|
4286
|
+
* @param homeAccountId
|
|
4287
|
+
* @param environment
|
|
4613
4288
|
*/
|
|
4614
|
-
static
|
|
4615
|
-
|
|
4616
|
-
|
|
4617
|
-
|
|
4618
|
-
|
|
4619
|
-
|
|
4620
|
-
|
|
4289
|
+
static generateAccountIdForCacheKey(homeAccountId, environment) {
|
|
4290
|
+
const accountId = [homeAccountId, environment];
|
|
4291
|
+
return accountId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
|
4292
|
+
}
|
|
4293
|
+
/**
|
|
4294
|
+
* Generates Credential Id for keys
|
|
4295
|
+
* @param credentialType
|
|
4296
|
+
* @param realm
|
|
4297
|
+
* @param clientId
|
|
4298
|
+
* @param familyId
|
|
4299
|
+
*/
|
|
4300
|
+
static generateCredentialIdForCacheKey(credentialType, clientId, realm, familyId) {
|
|
4301
|
+
const clientOrFamilyId = credentialType === CredentialType.REFRESH_TOKEN
|
|
4302
|
+
? familyId || clientId
|
|
4303
|
+
: clientId;
|
|
4304
|
+
const credentialId = [
|
|
4305
|
+
credentialType,
|
|
4306
|
+
clientOrFamilyId,
|
|
4307
|
+
realm || Constants.EMPTY_STRING,
|
|
4308
|
+
];
|
|
4309
|
+
return credentialId.join(Separators.CACHE_KEY_SEPARATOR).toLowerCase();
|
|
4310
|
+
}
|
|
4311
|
+
/**
|
|
4312
|
+
* Generate target key component as per schema: <target>
|
|
4313
|
+
*/
|
|
4314
|
+
static generateTargetForCacheKey(scopes) {
|
|
4315
|
+
return (scopes || Constants.EMPTY_STRING).toLowerCase();
|
|
4316
|
+
}
|
|
4317
|
+
/**
|
|
4318
|
+
* Generate requested claims key component as per schema: <requestedClaims>
|
|
4319
|
+
*/
|
|
4320
|
+
static generateClaimsHashForCacheKey(requestedClaimsHash) {
|
|
4321
|
+
return (requestedClaimsHash || Constants.EMPTY_STRING).toLowerCase();
|
|
4322
|
+
}
|
|
4323
|
+
/**
|
|
4324
|
+
* Generate scheme key componenet as per schema: <scheme>
|
|
4325
|
+
*/
|
|
4326
|
+
static generateSchemeForCacheKey(tokenType) {
|
|
4327
|
+
/*
|
|
4328
|
+
* PoP Tokens and SSH certs include scheme in cache key
|
|
4329
|
+
* Cast to lowercase to handle "bearer" from ADFS
|
|
4330
|
+
*/
|
|
4331
|
+
return tokenType &&
|
|
4332
|
+
tokenType.toLowerCase() !==
|
|
4333
|
+
AuthenticationScheme.BEARER.toLowerCase()
|
|
4334
|
+
? tokenType.toLowerCase()
|
|
4335
|
+
: Constants.EMPTY_STRING;
|
|
4621
4336
|
}
|
|
4337
|
+
}
|
|
4338
|
+
|
|
4339
|
+
/*
|
|
4340
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4341
|
+
* Licensed under the MIT License.
|
|
4342
|
+
*/
|
|
4343
|
+
/**
|
|
4344
|
+
* ID_TOKEN Cache
|
|
4345
|
+
*
|
|
4346
|
+
* Key:Value Schema:
|
|
4347
|
+
*
|
|
4348
|
+
* Key Example: uid.utid-login.microsoftonline.com-idtoken-clientId-contoso.com-
|
|
4349
|
+
*
|
|
4350
|
+
* Value Schema:
|
|
4351
|
+
* {
|
|
4352
|
+
* homeAccountId: home account identifier for the auth scheme,
|
|
4353
|
+
* environment: entity that issued the token, represented as a full host
|
|
4354
|
+
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
|
4355
|
+
* clientId: client ID of the application
|
|
4356
|
+
* secret: Actual credential as a string
|
|
4357
|
+
* realm: Full tenant or organizational identifier that the account belongs to
|
|
4358
|
+
* }
|
|
4359
|
+
*/
|
|
4360
|
+
class IdTokenEntity extends CredentialEntity {
|
|
4622
4361
|
/**
|
|
4623
|
-
*
|
|
4624
|
-
* @param
|
|
4362
|
+
* Create IdTokenEntity
|
|
4363
|
+
* @param homeAccountId
|
|
4364
|
+
* @param authenticationResult
|
|
4365
|
+
* @param clientId
|
|
4366
|
+
* @param authority
|
|
4625
4367
|
*/
|
|
4626
|
-
static
|
|
4627
|
-
|
|
4368
|
+
static createIdTokenEntity(homeAccountId, environment, idToken, clientId, tenantId) {
|
|
4369
|
+
const idTokenEntity = new IdTokenEntity();
|
|
4370
|
+
idTokenEntity.credentialType = CredentialType.ID_TOKEN;
|
|
4371
|
+
idTokenEntity.homeAccountId = homeAccountId;
|
|
4372
|
+
idTokenEntity.environment = environment;
|
|
4373
|
+
idTokenEntity.clientId = clientId;
|
|
4374
|
+
idTokenEntity.secret = idToken;
|
|
4375
|
+
idTokenEntity.realm = tenantId;
|
|
4376
|
+
return idTokenEntity;
|
|
4628
4377
|
}
|
|
4629
4378
|
/**
|
|
4630
|
-
*
|
|
4631
|
-
* @param
|
|
4632
|
-
* @param tenantId The tenant id to replace
|
|
4379
|
+
* Validates an entity: checks for all expected params
|
|
4380
|
+
* @param entity
|
|
4633
4381
|
*/
|
|
4634
|
-
|
|
4635
|
-
|
|
4636
|
-
|
|
4637
|
-
if (tenantId &&
|
|
4638
|
-
pathArray.length !== 0 &&
|
|
4639
|
-
(pathArray[0] === AADAuthorityConstants.COMMON ||
|
|
4640
|
-
pathArray[0] === AADAuthorityConstants.ORGANIZATIONS)) {
|
|
4641
|
-
pathArray[0] = tenantId;
|
|
4382
|
+
static isIdTokenEntity(entity) {
|
|
4383
|
+
if (!entity) {
|
|
4384
|
+
return false;
|
|
4642
4385
|
}
|
|
4643
|
-
return
|
|
4386
|
+
return (entity.hasOwnProperty("homeAccountId") &&
|
|
4387
|
+
entity.hasOwnProperty("environment") &&
|
|
4388
|
+
entity.hasOwnProperty("credentialType") &&
|
|
4389
|
+
entity.hasOwnProperty("realm") &&
|
|
4390
|
+
entity.hasOwnProperty("clientId") &&
|
|
4391
|
+
entity.hasOwnProperty("secret") &&
|
|
4392
|
+
entity["credentialType"] === CredentialType.ID_TOKEN);
|
|
4644
4393
|
}
|
|
4394
|
+
}
|
|
4395
|
+
|
|
4396
|
+
/*
|
|
4397
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4398
|
+
* Licensed under the MIT License.
|
|
4399
|
+
*/
|
|
4400
|
+
/**
|
|
4401
|
+
* Utility class which exposes functions for managing date and time operations.
|
|
4402
|
+
*/
|
|
4403
|
+
class TimeUtils {
|
|
4645
4404
|
/**
|
|
4646
|
-
*
|
|
4405
|
+
* return the current time in Unix time (seconds).
|
|
4647
4406
|
*/
|
|
4648
|
-
|
|
4649
|
-
|
|
4407
|
+
static nowSeconds() {
|
|
4408
|
+
// Date.getTime() returns in milliseconds.
|
|
4409
|
+
return Math.round(new Date().getTime() / 1000.0);
|
|
4650
4410
|
}
|
|
4651
4411
|
/**
|
|
4652
|
-
*
|
|
4653
|
-
* @
|
|
4412
|
+
* check if a token is expired based on given UTC time in seconds.
|
|
4413
|
+
* @param expiresOn
|
|
4654
4414
|
*/
|
|
4655
|
-
|
|
4656
|
-
//
|
|
4657
|
-
const
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
throw ClientConfigurationError.createUrlParseError(`Given url string: ${this.urlString}`);
|
|
4662
|
-
}
|
|
4663
|
-
// Url component object
|
|
4664
|
-
const urlComponents = {
|
|
4665
|
-
Protocol: match[1],
|
|
4666
|
-
HostNameAndPort: match[4],
|
|
4667
|
-
AbsolutePath: match[5],
|
|
4668
|
-
QueryString: match[7],
|
|
4669
|
-
};
|
|
4670
|
-
let pathSegments = urlComponents.AbsolutePath.split("/");
|
|
4671
|
-
pathSegments = pathSegments.filter((val) => val && val.length > 0); // remove empty elements
|
|
4672
|
-
urlComponents.PathSegments = pathSegments;
|
|
4673
|
-
if (!StringUtils.isEmpty(urlComponents.QueryString) &&
|
|
4674
|
-
urlComponents.QueryString.endsWith("/")) {
|
|
4675
|
-
urlComponents.QueryString = urlComponents.QueryString.substring(0, urlComponents.QueryString.length - 1);
|
|
4676
|
-
}
|
|
4677
|
-
return urlComponents;
|
|
4678
|
-
}
|
|
4679
|
-
static getDomainFromUrl(url) {
|
|
4680
|
-
const regEx = RegExp("^([^:/?#]+://)?([^/?#]*)");
|
|
4681
|
-
const match = url.match(regEx);
|
|
4682
|
-
if (!match) {
|
|
4683
|
-
throw ClientConfigurationError.createUrlParseError(`Given url string: ${url}`);
|
|
4684
|
-
}
|
|
4685
|
-
return match[2];
|
|
4686
|
-
}
|
|
4687
|
-
static getAbsoluteUrl(relativeUrl, baseUrl) {
|
|
4688
|
-
if (relativeUrl[0] === Constants.FORWARD_SLASH) {
|
|
4689
|
-
const url = new UrlString(baseUrl);
|
|
4690
|
-
const baseComponents = url.getUrlComponents();
|
|
4691
|
-
return (baseComponents.Protocol +
|
|
4692
|
-
"//" +
|
|
4693
|
-
baseComponents.HostNameAndPort +
|
|
4694
|
-
relativeUrl);
|
|
4695
|
-
}
|
|
4696
|
-
return relativeUrl;
|
|
4415
|
+
static isTokenExpired(expiresOn, offset) {
|
|
4416
|
+
// check for access token expiry
|
|
4417
|
+
const expirationSec = Number(expiresOn) || 0;
|
|
4418
|
+
const offsetCurrentTimeSec = TimeUtils.nowSeconds() + offset;
|
|
4419
|
+
// If current time + offset is greater than token expiration time, then token is expired.
|
|
4420
|
+
return offsetCurrentTimeSec > expirationSec;
|
|
4697
4421
|
}
|
|
4698
4422
|
/**
|
|
4699
|
-
*
|
|
4700
|
-
*
|
|
4423
|
+
* If the current time is earlier than the time that a token was cached at, we must discard the token
|
|
4424
|
+
* i.e. The system clock was turned back after acquiring the cached token
|
|
4425
|
+
* @param cachedAt
|
|
4426
|
+
* @param offset
|
|
4701
4427
|
*/
|
|
4702
|
-
static
|
|
4703
|
-
const
|
|
4704
|
-
|
|
4705
|
-
if (hashIndex2 > -1) {
|
|
4706
|
-
return hashString.substring(hashIndex2 + 2);
|
|
4707
|
-
}
|
|
4708
|
-
else if (hashIndex1 > -1) {
|
|
4709
|
-
return hashString.substring(hashIndex1 + 1);
|
|
4710
|
-
}
|
|
4711
|
-
return Constants.EMPTY_STRING;
|
|
4428
|
+
static wasClockTurnedBack(cachedAt) {
|
|
4429
|
+
const cachedAtSec = Number(cachedAt);
|
|
4430
|
+
return cachedAtSec > TimeUtils.nowSeconds();
|
|
4712
4431
|
}
|
|
4713
4432
|
/**
|
|
4714
|
-
*
|
|
4715
|
-
* @param
|
|
4433
|
+
* Waits for t number of milliseconds
|
|
4434
|
+
* @param t number
|
|
4435
|
+
* @param value T
|
|
4716
4436
|
*/
|
|
4717
|
-
static
|
|
4718
|
-
|
|
4719
|
-
const queryIndex2 = queryString.indexOf("/?");
|
|
4720
|
-
if (queryIndex2 > -1) {
|
|
4721
|
-
return queryString.substring(queryIndex2 + 2);
|
|
4722
|
-
}
|
|
4723
|
-
else if (queryIndex1 > -1) {
|
|
4724
|
-
return queryString.substring(queryIndex1 + 1);
|
|
4725
|
-
}
|
|
4726
|
-
return Constants.EMPTY_STRING;
|
|
4437
|
+
static delay(t, value) {
|
|
4438
|
+
return new Promise((resolve) => setTimeout(() => resolve(value), t));
|
|
4727
4439
|
}
|
|
4440
|
+
}
|
|
4441
|
+
|
|
4442
|
+
/*
|
|
4443
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4444
|
+
* Licensed under the MIT License.
|
|
4445
|
+
*/
|
|
4446
|
+
/**
|
|
4447
|
+
* ACCESS_TOKEN Credential Type
|
|
4448
|
+
*
|
|
4449
|
+
* Key:Value Schema:
|
|
4450
|
+
*
|
|
4451
|
+
* Key Example: uid.utid-login.microsoftonline.com-accesstoken-clientId-contoso.com-user.read
|
|
4452
|
+
*
|
|
4453
|
+
* Value Schema:
|
|
4454
|
+
* {
|
|
4455
|
+
* homeAccountId: home account identifier for the auth scheme,
|
|
4456
|
+
* environment: entity that issued the token, represented as a full host
|
|
4457
|
+
* credentialType: Type of credential as a string, can be one of the following: RefreshToken, AccessToken, IdToken, Password, Cookie, Certificate, Other
|
|
4458
|
+
* clientId: client ID of the application
|
|
4459
|
+
* secret: Actual credential as a string
|
|
4460
|
+
* familyId: Family ID identifier, usually only used for refresh tokens
|
|
4461
|
+
* realm: Full tenant or organizational identifier that the account belongs to
|
|
4462
|
+
* target: Permissions that are included in the token, or for refresh tokens, the resource identifier.
|
|
4463
|
+
* cachedAt: Absolute device time when entry was created in the cache.
|
|
4464
|
+
* expiresOn: Token expiry time, calculated based on current UTC time in seconds. Represented as a string.
|
|
4465
|
+
* extendedExpiresOn: Additional extended expiry time until when token is valid in case of server-side outage. Represented as string in UTC seconds.
|
|
4466
|
+
* keyId: used for POP and SSH tokenTypes
|
|
4467
|
+
* tokenType: Type of the token issued. Usually "Bearer"
|
|
4468
|
+
* }
|
|
4469
|
+
*/
|
|
4470
|
+
class AccessTokenEntity extends CredentialEntity {
|
|
4728
4471
|
/**
|
|
4729
|
-
*
|
|
4730
|
-
*
|
|
4731
|
-
*
|
|
4732
|
-
* @param
|
|
4472
|
+
* Create AccessTokenEntity
|
|
4473
|
+
* @param homeAccountId
|
|
4474
|
+
* @param environment
|
|
4475
|
+
* @param accessToken
|
|
4476
|
+
* @param clientId
|
|
4477
|
+
* @param tenantId
|
|
4478
|
+
* @param scopes
|
|
4479
|
+
* @param expiresOn
|
|
4480
|
+
* @param extExpiresOn
|
|
4733
4481
|
*/
|
|
4734
|
-
static
|
|
4735
|
-
const
|
|
4736
|
-
|
|
4737
|
-
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
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();
|
|
4749
4497
|
}
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
/**
|
|
4760
|
-
* Returns URL hash as server auth code response object.
|
|
4761
|
-
*/
|
|
4762
|
-
static getDeserializedHash(hash) {
|
|
4763
|
-
// Check if given hash is empty
|
|
4764
|
-
if (StringUtils.isEmpty(hash)) {
|
|
4765
|
-
return {};
|
|
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;
|
|
4766
4507
|
}
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4770
|
-
|
|
4771
|
-
|
|
4772
|
-
|
|
4773
|
-
|
|
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
|
+
}
|
|
4774
4528
|
}
|
|
4775
|
-
return
|
|
4529
|
+
return atEntity;
|
|
4776
4530
|
}
|
|
4777
4531
|
/**
|
|
4778
|
-
*
|
|
4532
|
+
* Validates an entity: checks for all expected params
|
|
4533
|
+
* @param entity
|
|
4779
4534
|
*/
|
|
4780
|
-
static
|
|
4781
|
-
|
|
4782
|
-
|
|
4783
|
-
return {};
|
|
4784
|
-
}
|
|
4785
|
-
// Strip the ? symbol if present
|
|
4786
|
-
const parsedQueryString = UrlString.parseQueryString(query);
|
|
4787
|
-
// If ? symbol was not present, above will return empty string, so give original query value
|
|
4788
|
-
const deserializedQueryString = StringUtils.queryStringToObject(StringUtils.isEmpty(parsedQueryString)
|
|
4789
|
-
? query
|
|
4790
|
-
: parsedQueryString);
|
|
4791
|
-
// Check if deserialization didn't work
|
|
4792
|
-
if (!deserializedQueryString) {
|
|
4793
|
-
throw ClientAuthError.createHashNotDeserializedError(JSON.stringify(deserializedQueryString));
|
|
4535
|
+
static isAccessTokenEntity(entity) {
|
|
4536
|
+
if (!entity) {
|
|
4537
|
+
return false;
|
|
4794
4538
|
}
|
|
4795
|
-
return
|
|
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));
|
|
4796
4549
|
}
|
|
4550
|
+
}
|
|
4551
|
+
|
|
4552
|
+
/*
|
|
4553
|
+
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
4554
|
+
* Licensed under the MIT License.
|
|
4555
|
+
*/
|
|
4556
|
+
/**
|
|
4557
|
+
* REFRESH_TOKEN Cache
|
|
4558
|
+
*
|
|
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
|
+
* }
|
|
4574
|
+
*/
|
|
4575
|
+
class RefreshTokenEntity extends CredentialEntity {
|
|
4797
4576
|
/**
|
|
4798
|
-
*
|
|
4799
|
-
*
|
|
4577
|
+
* Create RefreshTokenEntity
|
|
4578
|
+
* @param homeAccountId
|
|
4579
|
+
* @param authenticationResult
|
|
4580
|
+
* @param clientId
|
|
4581
|
+
* @param authority
|
|
4800
4582
|
*/
|
|
4801
|
-
static
|
|
4802
|
-
const
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4808
|
-
|
|
4809
|
-
|
|
4810
|
-
|
|
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;
|
|
4811
4594
|
}
|
|
4812
4595
|
/**
|
|
4813
|
-
*
|
|
4596
|
+
* Validates an entity: checks for all expected params
|
|
4597
|
+
* @param entity
|
|
4814
4598
|
*/
|
|
4815
|
-
static
|
|
4816
|
-
if (
|
|
4817
|
-
// Hash doesn't contain key/value pairs
|
|
4599
|
+
static isRefreshTokenEntity(entity) {
|
|
4600
|
+
if (!entity) {
|
|
4818
4601
|
return false;
|
|
4819
4602
|
}
|
|
4820
|
-
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
4824
|
-
|
|
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);
|
|
4825
4609
|
}
|
|
4826
4610
|
}
|
|
4827
4611
|
|
|
@@ -4830,227 +4614,444 @@ class UrlString {
|
|
|
4830
4614
|
* Licensed under the MIT License.
|
|
4831
4615
|
*/
|
|
4832
4616
|
/**
|
|
4833
|
-
*
|
|
4834
|
-
*
|
|
4835
|
-
* @export
|
|
4836
|
-
* @enum {number}
|
|
4617
|
+
* InteractionRequiredServerErrorMessage contains string constants used by error codes and messages returned by the server indicating interaction is required
|
|
4837
4618
|
*/
|
|
4838
|
-
const
|
|
4839
|
-
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
4853
|
-
|
|
4854
|
-
|
|
4855
|
-
|
|
4856
|
-
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4863
|
-
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
|
|
4868
|
-
|
|
4869
|
-
|
|
4870
|
-
|
|
4871
|
-
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
|
|
4876
|
-
* Used to read access tokens from the cache.
|
|
4877
|
-
*/
|
|
4878
|
-
SilentCacheClientAcquireToken: "silentCacheClientAcquireToken",
|
|
4879
|
-
/**
|
|
4880
|
-
* acquireToken API in the SilentIframeClient class (msal-browser).
|
|
4881
|
-
* Used to acquire a new set of tokens from the authorize endpoint in a hidden iframe.
|
|
4882
|
-
*/
|
|
4883
|
-
SilentIframeClientAcquireToken: "silentIframeClientAcquireToken",
|
|
4884
|
-
/**
|
|
4885
|
-
* acquireToken API in SilentRereshClient (msal-browser).
|
|
4886
|
-
* Used to acquire a new set of tokens from the token endpoint using a refresh token.
|
|
4887
|
-
*/
|
|
4888
|
-
SilentRefreshClientAcquireToken: "silentRefreshClientAcquireToken",
|
|
4889
|
-
/**
|
|
4890
|
-
* ssoSilent API (msal-browser).
|
|
4891
|
-
* Used to silently acquire an authorization code and set of tokens using a hidden iframe.
|
|
4892
|
-
*/
|
|
4893
|
-
SsoSilent: "ssoSilent",
|
|
4894
|
-
/**
|
|
4895
|
-
* getDiscoveredAuthority API in StandardInteractionClient class (msal-browser).
|
|
4896
|
-
* Used to load authority metadata for a request.
|
|
4897
|
-
*/
|
|
4898
|
-
StandardInteractionClientGetDiscoveredAuthority: "standardInteractionClientGetDiscoveredAuthority",
|
|
4899
|
-
/**
|
|
4900
|
-
* acquireToken APIs in msal-browser.
|
|
4901
|
-
* Used to make an /authorize endpoint call with native brokering enabled.
|
|
4902
|
-
*/
|
|
4903
|
-
FetchAccountIdWithNativeBroker: "fetchAccountIdWithNativeBroker",
|
|
4904
|
-
/**
|
|
4905
|
-
* acquireToken API in NativeInteractionClient class (msal-browser).
|
|
4906
|
-
* Used to acquire a token from Native component when native brokering is enabled.
|
|
4907
|
-
*/
|
|
4908
|
-
NativeInteractionClientAcquireToken: "nativeInteractionClientAcquireToken",
|
|
4909
|
-
/**
|
|
4910
|
-
* Time spent creating default headers for requests to token endpoint
|
|
4911
|
-
*/
|
|
4912
|
-
BaseClientCreateTokenRequestHeaders: "baseClientCreateTokenRequestHeaders",
|
|
4913
|
-
/**
|
|
4914
|
-
* Used to measure the time taken for completing embedded-broker handshake (PW-Broker).
|
|
4915
|
-
*/
|
|
4916
|
-
BrokerHandhshake: "brokerHandshake",
|
|
4917
|
-
/**
|
|
4918
|
-
* acquireTokenByRefreshToken API in BrokerClientApplication (PW-Broker) .
|
|
4919
|
-
*/
|
|
4920
|
-
AcquireTokenByRefreshTokenInBroker: "acquireTokenByRefreshTokenInBroker",
|
|
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
|
+
}
|
|
4921
4657
|
/**
|
|
4922
|
-
*
|
|
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
|
|
4923
4662
|
*/
|
|
4924
|
-
|
|
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
|
+
}
|
|
4925
4676
|
/**
|
|
4926
|
-
*
|
|
4677
|
+
* Creates an error thrown when the authorization code required for a token request is null or empty.
|
|
4927
4678
|
*/
|
|
4928
|
-
|
|
4679
|
+
static createNoTokensFoundError() {
|
|
4680
|
+
return new InteractionRequiredAuthError(InteractionRequiredAuthErrorMessage.noTokensFoundError.code, InteractionRequiredAuthErrorMessage.noTokensFoundError.desc);
|
|
4681
|
+
}
|
|
4929
4682
|
/**
|
|
4930
|
-
*
|
|
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
|
|
4931
4685
|
*/
|
|
4932
|
-
|
|
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 {
|
|
4933
4714
|
/**
|
|
4934
|
-
*
|
|
4715
|
+
* Appends user state with random guid, or returns random guid.
|
|
4716
|
+
* @param userState
|
|
4717
|
+
* @param randomGuid
|
|
4935
4718
|
*/
|
|
4936
|
-
|
|
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
|
+
}
|
|
4937
4725
|
/**
|
|
4938
|
-
*
|
|
4726
|
+
* Generates the state value used by the common library.
|
|
4727
|
+
* @param randomGuid
|
|
4728
|
+
* @param cryptoObj
|
|
4939
4729
|
*/
|
|
4940
|
-
|
|
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
|
+
}
|
|
4941
4744
|
/**
|
|
4942
|
-
*
|
|
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
|
|
4943
4748
|
*/
|
|
4944
|
-
|
|
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
|
+
}
|
|
4945
4797
|
/**
|
|
4946
|
-
*
|
|
4947
|
-
*
|
|
4798
|
+
* Ensure urls are lower case and end with a / character.
|
|
4799
|
+
* @param url
|
|
4948
4800
|
*/
|
|
4949
|
-
|
|
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
|
+
}
|
|
4950
4817
|
/**
|
|
4951
|
-
*
|
|
4952
|
-
* Internal API for acquiring token by silent Iframe
|
|
4818
|
+
* Throws if urlString passed is not a valid authority URI string.
|
|
4953
4819
|
*/
|
|
4954
|
-
|
|
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
|
+
}
|
|
4955
4839
|
/**
|
|
4956
|
-
*
|
|
4840
|
+
* Given a url and a query string return the url with provided query string appended
|
|
4841
|
+
* @param url
|
|
4842
|
+
* @param queryString
|
|
4957
4843
|
*/
|
|
4958
|
-
|
|
4844
|
+
static appendQueryString(url, queryString) {
|
|
4845
|
+
if (!queryString) {
|
|
4846
|
+
return url;
|
|
4847
|
+
}
|
|
4848
|
+
return url.indexOf("?") < 0
|
|
4849
|
+
? `${url}?${queryString}`
|
|
4850
|
+
: `${url}&${queryString}`;
|
|
4851
|
+
}
|
|
4959
4852
|
/**
|
|
4960
|
-
*
|
|
4853
|
+
* Returns a url with the hash removed
|
|
4854
|
+
* @param url
|
|
4961
4855
|
*/
|
|
4962
|
-
|
|
4963
|
-
|
|
4856
|
+
static removeHashFromUrl(url) {
|
|
4857
|
+
return UrlString.canonicalizeUri(url.split("#")[0]);
|
|
4858
|
+
}
|
|
4964
4859
|
/**
|
|
4965
|
-
*
|
|
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
|
|
4966
4863
|
*/
|
|
4967
|
-
|
|
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
|
+
}
|
|
4968
4875
|
/**
|
|
4969
|
-
*
|
|
4876
|
+
* Returns the anchor part(#) of the URL
|
|
4970
4877
|
*/
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4878
|
+
getHash() {
|
|
4879
|
+
return UrlString.parseHash(this.urlString);
|
|
4880
|
+
}
|
|
4974
4881
|
/**
|
|
4975
|
-
*
|
|
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.
|
|
4976
4884
|
*/
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
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
|
+
}
|
|
4981
4928
|
/**
|
|
4982
|
-
*
|
|
4929
|
+
* Parses hash string from given string. Returns empty string if no hash symbol is found.
|
|
4930
|
+
* @param hashString
|
|
4983
4931
|
*/
|
|
4984
|
-
|
|
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
|
+
}
|
|
4985
4943
|
/**
|
|
4986
|
-
*
|
|
4944
|
+
* Parses query string from given string. Returns empty string if no query symbol is found.
|
|
4945
|
+
* @param queryString
|
|
4987
4946
|
*/
|
|
4988
|
-
|
|
4989
|
-
|
|
4990
|
-
|
|
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
|
+
}
|
|
4991
4958
|
/**
|
|
4992
|
-
*
|
|
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
|
|
4993
4963
|
*/
|
|
4994
|
-
|
|
4995
|
-
|
|
4996
|
-
|
|
4997
|
-
|
|
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
|
+
}
|
|
4998
4989
|
/**
|
|
4999
|
-
*
|
|
4990
|
+
* Returns URL hash as server auth code response object.
|
|
5000
4991
|
*/
|
|
5001
|
-
|
|
5002
|
-
|
|
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
|
+
}
|
|
5003
5007
|
/**
|
|
5004
|
-
*
|
|
5008
|
+
* Returns URL query string as server auth code response object.
|
|
5005
5009
|
*/
|
|
5006
|
-
|
|
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
|
+
}
|
|
5007
5025
|
/**
|
|
5008
|
-
*
|
|
5026
|
+
* Returns either deserialized query string or deserialized hash, depending on the serverResponseType
|
|
5027
|
+
* as a server auth code response object.
|
|
5009
5028
|
*/
|
|
5010
|
-
|
|
5011
|
-
|
|
5012
|
-
|
|
5013
|
-
|
|
5014
|
-
|
|
5015
|
-
|
|
5016
|
-
|
|
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
|
+
}
|
|
5017
5040
|
/**
|
|
5018
|
-
*
|
|
5041
|
+
* Check if the hash of the URL string contains known properties
|
|
5019
5042
|
*/
|
|
5020
|
-
|
|
5021
|
-
|
|
5022
|
-
|
|
5023
|
-
|
|
5024
|
-
|
|
5025
|
-
|
|
5026
|
-
|
|
5027
|
-
|
|
5028
|
-
|
|
5029
|
-
|
|
5030
|
-
|
|
5031
|
-
}
|
|
5032
|
-
/**
|
|
5033
|
-
* State of the performance event.
|
|
5034
|
-
*
|
|
5035
|
-
* @export
|
|
5036
|
-
* @enum {number}
|
|
5037
|
-
*/
|
|
5038
|
-
const PerformanceEventStatus = {
|
|
5039
|
-
NotStarted: 0,
|
|
5040
|
-
InProgress: 1,
|
|
5041
|
-
Completed: 2,
|
|
5042
|
-
};
|
|
5043
|
-
const IntFields = new Set([
|
|
5044
|
-
"accessTokenSize",
|
|
5045
|
-
"durationMs",
|
|
5046
|
-
"idTokenSize",
|
|
5047
|
-
"matsSilentStatus",
|
|
5048
|
-
"matsHttpStatus",
|
|
5049
|
-
"refreshTokenSize",
|
|
5050
|
-
"queuedTimeMs",
|
|
5051
|
-
"startTimeMs",
|
|
5052
|
-
"status",
|
|
5053
|
-
]);
|
|
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
|
+
}
|
|
5054
5055
|
|
|
5055
5056
|
/*
|
|
5056
5057
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -5060,6 +5061,7 @@ const KeyLocation = {
|
|
|
5060
5061
|
SW: "sw",
|
|
5061
5062
|
UHW: "uhw",
|
|
5062
5063
|
};
|
|
5064
|
+
/** @internal */
|
|
5063
5065
|
class PopTokenGenerator {
|
|
5064
5066
|
constructor(cryptoUtils, performanceClient) {
|
|
5065
5067
|
this.cryptoUtils = cryptoUtils;
|
|
@@ -5234,6 +5236,7 @@ class AppMetadataEntity {
|
|
|
5234
5236
|
*/
|
|
5235
5237
|
/**
|
|
5236
5238
|
* Class that handles response parsing.
|
|
5239
|
+
* @internal
|
|
5237
5240
|
*/
|
|
5238
5241
|
class ResponseHandler {
|
|
5239
5242
|
constructor(clientId, cacheStorage, cryptoObj, logger, serializableCache, persistencePlugin, performanceClient) {
|
|
@@ -5290,17 +5293,37 @@ class ResponseHandler {
|
|
|
5290
5293
|
/**
|
|
5291
5294
|
* Function which validates server authorization token response.
|
|
5292
5295
|
* @param serverResponse
|
|
5296
|
+
* @param refreshAccessToken
|
|
5293
5297
|
*/
|
|
5294
|
-
validateTokenResponse(serverResponse) {
|
|
5298
|
+
validateTokenResponse(serverResponse, refreshAccessToken) {
|
|
5295
5299
|
// Check for error
|
|
5296
5300
|
if (serverResponse.error ||
|
|
5297
5301
|
serverResponse.error_description ||
|
|
5298
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
|
+
}
|
|
5299
5323
|
if (InteractionRequiredAuthError.isInteractionRequiredError(serverResponse.error, serverResponse.error_description, serverResponse.suberror)) {
|
|
5300
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);
|
|
5301
5325
|
}
|
|
5302
|
-
|
|
5303
|
-
throw new ServerError(serverResponse.error, errString, serverResponse.suberror);
|
|
5326
|
+
throw serverError;
|
|
5304
5327
|
}
|
|
5305
5328
|
}
|
|
5306
5329
|
/**
|
|
@@ -5311,27 +5334,26 @@ class ResponseHandler {
|
|
|
5311
5334
|
async handleServerTokenResponse(serverTokenResponse, authority, reqTimestamp, request, authCodePayload, userAssertionHash, handlingRefreshTokenResponse, forceCacheRefreshTokenResponse, serverRequestId) {
|
|
5312
5335
|
this.performanceClient?.addQueueMeasurement(PerformanceEvents.HandleServerTokenResponse, serverTokenResponse.correlation_id);
|
|
5313
5336
|
// create an idToken object (not entity)
|
|
5314
|
-
let
|
|
5337
|
+
let idTokenClaims;
|
|
5315
5338
|
if (serverTokenResponse.id_token) {
|
|
5316
|
-
|
|
5339
|
+
idTokenClaims = extractTokenClaims(serverTokenResponse.id_token || Constants.EMPTY_STRING, this.cryptoObj.base64Decode);
|
|
5317
5340
|
// token nonce check (TODO: Add a warning if no nonce is given?)
|
|
5318
|
-
if (authCodePayload &&
|
|
5319
|
-
|
|
5320
|
-
if (idTokenObj.claims.nonce !== authCodePayload.nonce) {
|
|
5341
|
+
if (authCodePayload && authCodePayload.nonce) {
|
|
5342
|
+
if (idTokenClaims.nonce !== authCodePayload.nonce) {
|
|
5321
5343
|
throw ClientAuthError.createNonceMismatchError();
|
|
5322
5344
|
}
|
|
5323
5345
|
}
|
|
5324
5346
|
// token max_age check
|
|
5325
5347
|
if (request.maxAge || request.maxAge === 0) {
|
|
5326
|
-
const authTime =
|
|
5348
|
+
const authTime = idTokenClaims.auth_time;
|
|
5327
5349
|
if (!authTime) {
|
|
5328
5350
|
throw ClientAuthError.createAuthTimeNotFoundError();
|
|
5329
5351
|
}
|
|
5330
|
-
|
|
5352
|
+
checkMaxAge(authTime, request.maxAge);
|
|
5331
5353
|
}
|
|
5332
5354
|
}
|
|
5333
5355
|
// generate homeAccountId
|
|
5334
|
-
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);
|
|
5335
5357
|
// save the response tokens
|
|
5336
5358
|
let requestStateObj;
|
|
5337
5359
|
if (!!authCodePayload && !!authCodePayload.state) {
|
|
@@ -5340,7 +5362,7 @@ class ResponseHandler {
|
|
|
5340
5362
|
// Add keyId from request to serverTokenResponse if defined
|
|
5341
5363
|
serverTokenResponse.key_id =
|
|
5342
5364
|
serverTokenResponse.key_id || request.sshKid || undefined;
|
|
5343
|
-
const cacheRecord = this.generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request,
|
|
5365
|
+
const cacheRecord = this.generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenClaims, userAssertionHash, authCodePayload);
|
|
5344
5366
|
let cacheContext;
|
|
5345
5367
|
try {
|
|
5346
5368
|
if (this.persistencePlugin && this.serializableCache) {
|
|
@@ -5361,7 +5383,7 @@ class ResponseHandler {
|
|
|
5361
5383
|
const account = this.cacheStorage.getAccount(key);
|
|
5362
5384
|
if (!account) {
|
|
5363
5385
|
this.logger.warning("Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache");
|
|
5364
|
-
return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request,
|
|
5386
|
+
return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenClaims, requestStateObj, undefined, serverRequestId);
|
|
5365
5387
|
}
|
|
5366
5388
|
}
|
|
5367
5389
|
await this.cacheStorage.saveCacheRecord(cacheRecord, request.storeInCache);
|
|
@@ -5374,7 +5396,7 @@ class ResponseHandler {
|
|
|
5374
5396
|
await this.persistencePlugin.afterCacheAccess(cacheContext);
|
|
5375
5397
|
}
|
|
5376
5398
|
}
|
|
5377
|
-
return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request,
|
|
5399
|
+
return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenClaims, requestStateObj, serverTokenResponse, serverRequestId);
|
|
5378
5400
|
}
|
|
5379
5401
|
/**
|
|
5380
5402
|
* Generates CacheRecord
|
|
@@ -5382,20 +5404,19 @@ class ResponseHandler {
|
|
|
5382
5404
|
* @param idTokenObj
|
|
5383
5405
|
* @param authority
|
|
5384
5406
|
*/
|
|
5385
|
-
generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request,
|
|
5407
|
+
generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenClaims, userAssertionHash, authCodePayload) {
|
|
5386
5408
|
const env = authority.getPreferredCache();
|
|
5387
|
-
if (
|
|
5409
|
+
if (!env) {
|
|
5388
5410
|
throw ClientAuthError.createInvalidCacheEnvironmentError();
|
|
5389
5411
|
}
|
|
5390
5412
|
// IdToken: non AAD scenarios can have empty realm
|
|
5391
5413
|
let cachedIdToken;
|
|
5392
5414
|
let cachedAccount;
|
|
5393
|
-
if (
|
|
5394
|
-
|
|
5395
|
-
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 || "");
|
|
5396
5417
|
cachedAccount = AccountEntity.createAccount({
|
|
5397
5418
|
homeAccountId: this.homeAccountIdentifier,
|
|
5398
|
-
idTokenClaims:
|
|
5419
|
+
idTokenClaims: idTokenClaims,
|
|
5399
5420
|
clientInfo: serverTokenResponse.client_info,
|
|
5400
5421
|
cloudGraphHostName: authCodePayload?.cloud_graph_host_name,
|
|
5401
5422
|
msGraphHost: authCodePayload?.msgraph_host,
|
|
@@ -5403,7 +5424,7 @@ class ResponseHandler {
|
|
|
5403
5424
|
}
|
|
5404
5425
|
// AccessToken
|
|
5405
5426
|
let cachedAccessToken = null;
|
|
5406
|
-
if (
|
|
5427
|
+
if (serverTokenResponse.access_token) {
|
|
5407
5428
|
// If scopes not returned in server response, use request scopes
|
|
5408
5429
|
const responseScopes = serverTokenResponse.scope
|
|
5409
5430
|
? ScopeSet.fromString(serverTokenResponse.scope)
|
|
@@ -5427,18 +5448,16 @@ class ResponseHandler {
|
|
|
5427
5448
|
? reqTimestamp + refreshIn
|
|
5428
5449
|
: undefined;
|
|
5429
5450
|
// non AAD scenarios can have empty realm
|
|
5430
|
-
cachedAccessToken = AccessTokenEntity.createAccessTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.access_token || Constants.EMPTY_STRING, this.clientId,
|
|
5431
|
-
? idTokenObj.claims.tid || Constants.EMPTY_STRING
|
|
5432
|
-
: 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);
|
|
5433
5452
|
}
|
|
5434
5453
|
// refreshToken
|
|
5435
5454
|
let cachedRefreshToken = null;
|
|
5436
|
-
if (
|
|
5455
|
+
if (serverTokenResponse.refresh_token) {
|
|
5437
5456
|
cachedRefreshToken = RefreshTokenEntity.createRefreshTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.refresh_token || Constants.EMPTY_STRING, this.clientId, serverTokenResponse.foci, userAssertionHash);
|
|
5438
5457
|
}
|
|
5439
5458
|
// appMetadata
|
|
5440
5459
|
let cachedAppMetadata = null;
|
|
5441
|
-
if (
|
|
5460
|
+
if (serverTokenResponse.foci) {
|
|
5442
5461
|
cachedAppMetadata = AppMetadataEntity.createAppMetadataEntity(this.clientId, env, serverTokenResponse.foci);
|
|
5443
5462
|
}
|
|
5444
5463
|
return new CacheRecord(cachedAccount, cachedIdToken, cachedAccessToken, cachedRefreshToken, cachedAppMetadata);
|
|
@@ -5453,11 +5472,12 @@ class ResponseHandler {
|
|
|
5453
5472
|
* @param fromTokenCache
|
|
5454
5473
|
* @param stateString
|
|
5455
5474
|
*/
|
|
5456
|
-
static async generateAuthenticationResult(cryptoObj, authority, cacheRecord, fromTokenCache, request,
|
|
5475
|
+
static async generateAuthenticationResult(cryptoObj, authority, cacheRecord, fromTokenCache, request, idTokenClaims, requestState, serverTokenResponse, requestId) {
|
|
5457
5476
|
let accessToken = Constants.EMPTY_STRING;
|
|
5458
5477
|
let responseScopes = [];
|
|
5459
5478
|
let expiresOn = null;
|
|
5460
5479
|
let extExpiresOn;
|
|
5480
|
+
let refreshOn;
|
|
5461
5481
|
let familyId = Constants.EMPTY_STRING;
|
|
5462
5482
|
if (cacheRecord.accessToken) {
|
|
5463
5483
|
if (cacheRecord.accessToken.tokenType === AuthenticationScheme.POP) {
|
|
@@ -5474,17 +5494,18 @@ class ResponseHandler {
|
|
|
5474
5494
|
responseScopes = ScopeSet.fromString(cacheRecord.accessToken.target).asArray();
|
|
5475
5495
|
expiresOn = new Date(Number(cacheRecord.accessToken.expiresOn) * 1000);
|
|
5476
5496
|
extExpiresOn = new Date(Number(cacheRecord.accessToken.extendedExpiresOn) * 1000);
|
|
5497
|
+
if (cacheRecord.accessToken.refreshOn) {
|
|
5498
|
+
refreshOn = new Date(Number(cacheRecord.accessToken.refreshOn) * 1000);
|
|
5499
|
+
}
|
|
5477
5500
|
}
|
|
5478
5501
|
if (cacheRecord.appMetadata) {
|
|
5479
5502
|
familyId =
|
|
5480
5503
|
cacheRecord.appMetadata.familyId === THE_FAMILY_ID
|
|
5481
5504
|
? THE_FAMILY_ID
|
|
5482
|
-
:
|
|
5505
|
+
: "";
|
|
5483
5506
|
}
|
|
5484
|
-
const uid =
|
|
5485
|
-
|
|
5486
|
-
Constants.EMPTY_STRING;
|
|
5487
|
-
const tid = idTokenObj?.claims.tid || Constants.EMPTY_STRING;
|
|
5507
|
+
const uid = idTokenClaims?.oid || idTokenClaims?.sub || "";
|
|
5508
|
+
const tid = idTokenClaims?.tid || "";
|
|
5488
5509
|
// for hybrid + native bridge enablement, send back the native account Id
|
|
5489
5510
|
if (serverTokenResponse?.spa_accountid && !!cacheRecord.account) {
|
|
5490
5511
|
cacheRecord.account.nativeAccountId =
|
|
@@ -5498,14 +5519,15 @@ class ResponseHandler {
|
|
|
5498
5519
|
account: cacheRecord.account
|
|
5499
5520
|
? cacheRecord.account.getAccountInfo()
|
|
5500
5521
|
: null,
|
|
5501
|
-
idToken:
|
|
5502
|
-
idTokenClaims:
|
|
5522
|
+
idToken: cacheRecord?.idToken?.secret || "",
|
|
5523
|
+
idTokenClaims: idTokenClaims || {},
|
|
5503
5524
|
accessToken: accessToken,
|
|
5504
5525
|
fromCache: fromTokenCache,
|
|
5505
5526
|
expiresOn: expiresOn,
|
|
5527
|
+
extExpiresOn: extExpiresOn,
|
|
5528
|
+
refreshOn: refreshOn,
|
|
5506
5529
|
correlationId: request.correlationId,
|
|
5507
5530
|
requestId: requestId || Constants.EMPTY_STRING,
|
|
5508
|
-
extExpiresOn: extExpiresOn,
|
|
5509
5531
|
familyId: familyId,
|
|
5510
5532
|
tokenType: cacheRecord.accessToken?.tokenType || Constants.EMPTY_STRING,
|
|
5511
5533
|
state: requestState
|
|
@@ -5520,12 +5542,99 @@ class ResponseHandler {
|
|
|
5520
5542
|
}
|
|
5521
5543
|
}
|
|
5522
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
|
+
|
|
5523
5631
|
/*
|
|
5524
5632
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
5525
5633
|
* Licensed under the MIT License.
|
|
5526
5634
|
*/
|
|
5527
5635
|
/**
|
|
5528
5636
|
* Oauth2.0 Authorization Code client
|
|
5637
|
+
* @internal
|
|
5529
5638
|
*/
|
|
5530
5639
|
class AuthorizationCodeClient extends BaseClient {
|
|
5531
5640
|
constructor(configuration, performanceClient) {
|
|
@@ -5547,8 +5656,7 @@ class AuthorizationCodeClient extends BaseClient {
|
|
|
5547
5656
|
*/
|
|
5548
5657
|
async getAuthCodeUrl(request) {
|
|
5549
5658
|
this.performanceClient?.addQueueMeasurement(PerformanceEvents.GetAuthCodeUrl, request.correlationId);
|
|
5550
|
-
this.
|
|
5551
|
-
const queryString = await this.createAuthCodeUrlQueryString(request);
|
|
5659
|
+
const queryString = await invokeAsync(this.createAuthCodeUrlQueryString.bind(this), PerformanceEvents.AuthClientCreateQueryString, this.logger, this.performanceClient, request.correlationId)(request);
|
|
5552
5660
|
return UrlString.appendQueryString(this.authority.authorizationEndpoint, queryString);
|
|
5553
5661
|
}
|
|
5554
5662
|
/**
|
|
@@ -5557,46 +5665,18 @@ class AuthorizationCodeClient extends BaseClient {
|
|
|
5557
5665
|
* @param request
|
|
5558
5666
|
*/
|
|
5559
5667
|
async acquireToken(request, authCodePayload) {
|
|
5560
|
-
|
|
5668
|
+
this.performanceClient?.addQueueMeasurement(PerformanceEvents.AuthClientAcquireToken, request.correlationId);
|
|
5669
|
+
if (!request.code) {
|
|
5561
5670
|
throw ClientAuthError.createTokenRequestCannotBeMadeError();
|
|
5562
5671
|
}
|
|
5563
|
-
this.performanceClient?.addQueueMeasurement(PerformanceEvents.AuthClientAcquireToken, request.correlationId);
|
|
5564
|
-
const atsMeasurement = this.performanceClient?.startMeasurement(
|
|
5565
|
-
// @ts-ignore
|
|
5566
|
-
"AuthCodeClientAcquireToken", request.correlationId);
|
|
5567
|
-
this.logger.info("in acquireToken call in auth-code client");
|
|
5568
5672
|
const reqTimestamp = TimeUtils.nowSeconds();
|
|
5569
|
-
this.
|
|
5570
|
-
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);
|
|
5571
5674
|
// Retrieve requestId from response headers
|
|
5572
5675
|
const requestId = response.headers?.[HeaderNames.X_MS_REQUEST_ID];
|
|
5573
|
-
const httpVerAuthority = response.headers?.[HeaderNames.X_MS_HTTP_VERSION];
|
|
5574
|
-
if (httpVerAuthority) {
|
|
5575
|
-
atsMeasurement?.add({
|
|
5576
|
-
httpVerAuthority,
|
|
5577
|
-
});
|
|
5578
|
-
}
|
|
5579
5676
|
const responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin, this.performanceClient);
|
|
5580
5677
|
// Validate response. This function throws a server error if an error is returned by the server.
|
|
5581
5678
|
responseHandler.validateTokenResponse(response.body);
|
|
5582
|
-
|
|
5583
|
-
return responseHandler
|
|
5584
|
-
.handleServerTokenResponse(response.body, this.authority, reqTimestamp, request, authCodePayload, undefined, undefined, undefined, requestId)
|
|
5585
|
-
.then((result) => {
|
|
5586
|
-
atsMeasurement?.end({
|
|
5587
|
-
success: true,
|
|
5588
|
-
});
|
|
5589
|
-
return result;
|
|
5590
|
-
})
|
|
5591
|
-
.catch((error) => {
|
|
5592
|
-
this.logger.verbose("Error in fetching token in ACC", request.correlationId);
|
|
5593
|
-
atsMeasurement?.end({
|
|
5594
|
-
errorCode: error.errorCode,
|
|
5595
|
-
subErrorCode: error.subError,
|
|
5596
|
-
success: false,
|
|
5597
|
-
});
|
|
5598
|
-
throw error;
|
|
5599
|
-
});
|
|
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);
|
|
5600
5680
|
}
|
|
5601
5681
|
/**
|
|
5602
5682
|
* Handles the hash fragment response from public client code request. Returns a code response used by
|
|
@@ -5641,10 +5721,9 @@ class AuthorizationCodeClient extends BaseClient {
|
|
|
5641
5721
|
*/
|
|
5642
5722
|
async executeTokenRequest(authority, request) {
|
|
5643
5723
|
this.performanceClient?.addQueueMeasurement(PerformanceEvents.AuthClientExecuteTokenRequest, request.correlationId);
|
|
5644
|
-
this.performanceClient?.setPreQueueTime(PerformanceEvents.AuthClientCreateTokenRequestBody, request.correlationId);
|
|
5645
5724
|
const queryParametersString = this.createTokenQueryParameters(request);
|
|
5646
5725
|
const endpoint = UrlString.appendQueryString(authority.tokenEndpoint, queryParametersString);
|
|
5647
|
-
const requestBody = await this.createTokenRequestBody(request);
|
|
5726
|
+
const requestBody = await invokeAsync(this.createTokenRequestBody.bind(this), PerformanceEvents.AuthClientCreateTokenRequestBody, this.logger, this.performanceClient, request.correlationId)(request);
|
|
5648
5727
|
let ccsCredential = undefined;
|
|
5649
5728
|
if (request.clientInfo) {
|
|
5650
5729
|
try {
|
|
@@ -5670,7 +5749,7 @@ class AuthorizationCodeClient extends BaseClient {
|
|
|
5670
5749
|
shrClaims: request.shrClaims,
|
|
5671
5750
|
sshKid: request.sshKid,
|
|
5672
5751
|
};
|
|
5673
|
-
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);
|
|
5674
5753
|
}
|
|
5675
5754
|
/**
|
|
5676
5755
|
* Generates a map for all the params to be sent to the service
|
|
@@ -5899,7 +5978,7 @@ class AuthorizationCodeClient extends BaseClient {
|
|
|
5899
5978
|
if (request.state) {
|
|
5900
5979
|
parameterBuilder.addState(request.state);
|
|
5901
5980
|
}
|
|
5902
|
-
if (
|
|
5981
|
+
if (request.claims ||
|
|
5903
5982
|
(this.config.authOptions.clientCapabilities &&
|
|
5904
5983
|
this.config.authOptions.clientCapabilities.length > 0)) {
|
|
5905
5984
|
parameterBuilder.addClaims(request.claims, this.config.authOptions.clientCapabilities);
|
|
@@ -5964,6 +6043,7 @@ class AuthorizationCodeClient extends BaseClient {
|
|
|
5964
6043
|
*/
|
|
5965
6044
|
/**
|
|
5966
6045
|
* OAuth2.0 refresh token client
|
|
6046
|
+
* @internal
|
|
5967
6047
|
*/
|
|
5968
6048
|
class RefreshTokenClient extends BaseClient {
|
|
5969
6049
|
constructor(configuration, performanceClient) {
|
|
@@ -5976,15 +6056,6 @@ class RefreshTokenClient extends BaseClient {
|
|
|
5976
6056
|
const reqTimestamp = TimeUtils.nowSeconds();
|
|
5977
6057
|
this.performanceClient?.setPreQueueTime(PerformanceEvents.RefreshTokenClientExecuteTokenRequest, request.correlationId);
|
|
5978
6058
|
const response = await this.executeTokenRequest(request, this.authority);
|
|
5979
|
-
const httpVerToken = response.headers?.[HeaderNames.X_MS_HTTP_VERSION];
|
|
5980
|
-
atsMeasurement?.add({
|
|
5981
|
-
refreshTokenSize: response.body.refresh_token?.length || 0,
|
|
5982
|
-
});
|
|
5983
|
-
if (httpVerToken) {
|
|
5984
|
-
atsMeasurement?.add({
|
|
5985
|
-
httpVerToken,
|
|
5986
|
-
});
|
|
5987
|
-
}
|
|
5988
6059
|
// Retrieve requestId from response headers
|
|
5989
6060
|
const requestId = response.headers?.[HeaderNames.X_MS_REQUEST_ID];
|
|
5990
6061
|
const responseHandler = new ResponseHandler(this.config.authOptions.clientId, this.cacheManager, this.cryptoUtils, this.logger, this.config.serializableCache, this.config.persistencePlugin);
|
|
@@ -6107,7 +6178,7 @@ class RefreshTokenClient extends BaseClient {
|
|
|
6107
6178
|
shrClaims: request.shrClaims,
|
|
6108
6179
|
sshKid: request.sshKid,
|
|
6109
6180
|
};
|
|
6110
|
-
return this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint)
|
|
6181
|
+
return this.executePostToTokenEndpoint(endpoint, requestBody, headers, thumbprint, request.correlationId)
|
|
6111
6182
|
.then((result) => {
|
|
6112
6183
|
acquireTokenMeasurement?.end({
|
|
6113
6184
|
success: true,
|
|
@@ -6202,6 +6273,7 @@ class RefreshTokenClient extends BaseClient {
|
|
|
6202
6273
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
6203
6274
|
* Licensed under the MIT License.
|
|
6204
6275
|
*/
|
|
6276
|
+
/** @internal */
|
|
6205
6277
|
class SilentFlowClient extends BaseClient {
|
|
6206
6278
|
constructor(configuration, performanceClient) {
|
|
6207
6279
|
super(configuration, performanceClient);
|
|
@@ -6283,19 +6355,19 @@ class SilentFlowClient extends BaseClient {
|
|
|
6283
6355
|
* @param cacheRecord
|
|
6284
6356
|
*/
|
|
6285
6357
|
async generateResultFromCacheRecord(cacheRecord, request) {
|
|
6286
|
-
let
|
|
6358
|
+
let idTokenClaims;
|
|
6287
6359
|
if (cacheRecord.idToken) {
|
|
6288
|
-
|
|
6360
|
+
idTokenClaims = extractTokenClaims(cacheRecord.idToken.secret, this.config.cryptoInterface.base64Decode);
|
|
6289
6361
|
}
|
|
6290
6362
|
// token max_age check
|
|
6291
6363
|
if (request.maxAge || request.maxAge === 0) {
|
|
6292
|
-
const authTime =
|
|
6364
|
+
const authTime = idTokenClaims?.auth_time;
|
|
6293
6365
|
if (!authTime) {
|
|
6294
6366
|
throw ClientAuthError.createAuthTimeNotFoundError();
|
|
6295
6367
|
}
|
|
6296
|
-
|
|
6368
|
+
checkMaxAge(authTime, request.maxAge);
|
|
6297
6369
|
}
|
|
6298
|
-
return await ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, cacheRecord, true, request,
|
|
6370
|
+
return await ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, cacheRecord, true, request, idTokenClaims);
|
|
6299
6371
|
}
|
|
6300
6372
|
}
|
|
6301
6373
|
|
|
@@ -7199,6 +7271,7 @@ for (const key in InstanceDiscoveryMetadata) {
|
|
|
7199
7271
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
7200
7272
|
* Licensed under the MIT License.
|
|
7201
7273
|
*/
|
|
7274
|
+
/** @internal */
|
|
7202
7275
|
class AuthorityMetadataEntity {
|
|
7203
7276
|
constructor() {
|
|
7204
7277
|
this.expiresAt =
|
|
@@ -7407,6 +7480,7 @@ RegionDiscovery.IMDS_OPTIONS = {
|
|
|
7407
7480
|
/**
|
|
7408
7481
|
* The authority class validates the authority URIs used by the user, and retrieves the OpenID Configuration Data from the
|
|
7409
7482
|
* endpoint. It will store the pertinent config data in this object for use during token calls.
|
|
7483
|
+
* @internal
|
|
7410
7484
|
*/
|
|
7411
7485
|
class Authority {
|
|
7412
7486
|
constructor(authority, networkInterface, cacheManager, authorityOptions, logger, performanceClient, correlationId) {
|
|
@@ -7620,7 +7694,8 @@ class Authority {
|
|
|
7620
7694
|
get defaultOpenIdConfigurationEndpoint() {
|
|
7621
7695
|
const canonicalAuthorityHost = this.hostnameAndPort;
|
|
7622
7696
|
if (this.authorityType === AuthorityType.Adfs ||
|
|
7623
|
-
|
|
7697
|
+
(this.protocolMode !== ProtocolMode.AAD &&
|
|
7698
|
+
!this.isAliasOfKnownMicrosoftAuthority(canonicalAuthorityHost))) {
|
|
7624
7699
|
return `${this.canonicalAuthority}.well-known/openid-configuration`;
|
|
7625
7700
|
}
|
|
7626
7701
|
return `${this.canonicalAuthority}v2.0/.well-known/openid-configuration`;
|
|
@@ -8166,6 +8241,7 @@ Authority.reservedTenantDomains = new Set([
|
|
|
8166
8241
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
8167
8242
|
* Licensed under the MIT License.
|
|
8168
8243
|
*/
|
|
8244
|
+
/** @internal */
|
|
8169
8245
|
class AuthorityFactory {
|
|
8170
8246
|
/**
|
|
8171
8247
|
* Create an authority object of the correct type based on the url
|
|
@@ -8203,7 +8279,7 @@ class AuthorityFactory {
|
|
|
8203
8279
|
*/
|
|
8204
8280
|
static createInstance(authorityUrl, networkInterface, cacheManager, authorityOptions, logger, performanceClient, correlationId) {
|
|
8205
8281
|
// Throw error if authority url is empty
|
|
8206
|
-
if (
|
|
8282
|
+
if (!authorityUrl) {
|
|
8207
8283
|
throw ClientConfigurationError.createUrlEmptyError();
|
|
8208
8284
|
}
|
|
8209
8285
|
return new Authority(authorityUrl, networkInterface, cacheManager, authorityOptions, logger, performanceClient, correlationId);
|
|
@@ -8321,6 +8397,7 @@ class JoseHeaderError extends AuthError {
|
|
|
8321
8397
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
8322
8398
|
* Licensed under the MIT License.
|
|
8323
8399
|
*/
|
|
8400
|
+
/** @internal */
|
|
8324
8401
|
class JoseHeader {
|
|
8325
8402
|
constructor(options) {
|
|
8326
8403
|
this.typ = options.typ;
|
|
@@ -8414,6 +8491,7 @@ class AuthenticationHeaderParser {
|
|
|
8414
8491
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
8415
8492
|
* Licensed under the MIT License.
|
|
8416
8493
|
*/
|
|
8494
|
+
/** @internal */
|
|
8417
8495
|
class ServerTelemetryManager {
|
|
8418
8496
|
constructor(telemetryRequest, cacheManager) {
|
|
8419
8497
|
this.cacheOutcome = CacheOutcome.NO_CACHE_HIT;
|
|
@@ -8486,10 +8564,10 @@ class ServerTelemetryManager {
|
|
|
8486
8564
|
lastRequests.failedRequests.push(this.apiId, this.correlationId);
|
|
8487
8565
|
if (error instanceof Error && !!error && error.toString()) {
|
|
8488
8566
|
if (error instanceof AuthError) {
|
|
8489
|
-
if (
|
|
8567
|
+
if (error.subError) {
|
|
8490
8568
|
lastRequests.errors.push(error.subError);
|
|
8491
8569
|
}
|
|
8492
|
-
else if (
|
|
8570
|
+
else if (error.errorCode) {
|
|
8493
8571
|
lastRequests.errors.push(error.errorCode);
|
|
8494
8572
|
}
|
|
8495
8573
|
else {
|
|
@@ -9031,10 +9109,30 @@ class StubPerformanceMeasurement {
|
|
|
9031
9109
|
return null;
|
|
9032
9110
|
}
|
|
9033
9111
|
}
|
|
9034
|
-
class StubPerformanceClient
|
|
9112
|
+
class StubPerformanceClient {
|
|
9035
9113
|
generateId() {
|
|
9036
9114
|
return "callback-id";
|
|
9037
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
|
+
}
|
|
9038
9136
|
startPerformanceMeasurement() {
|
|
9039
9137
|
return new StubPerformanceMeasurement();
|
|
9040
9138
|
}
|
|
@@ -9111,7 +9209,7 @@ exports.DefaultStorageClass = DefaultStorageClass;
|
|
|
9111
9209
|
exports.Errors = Errors;
|
|
9112
9210
|
exports.GrantType = GrantType;
|
|
9113
9211
|
exports.HeaderNames = HeaderNames;
|
|
9114
|
-
exports.
|
|
9212
|
+
exports.HttpStatus = HttpStatus;
|
|
9115
9213
|
exports.IdTokenEntity = IdTokenEntity;
|
|
9116
9214
|
exports.IntFields = IntFields;
|
|
9117
9215
|
exports.InteractionRequiredAuthError = InteractionRequiredAuthError;
|
|
@@ -9154,5 +9252,7 @@ exports.TokenCacheContext = TokenCacheContext;
|
|
|
9154
9252
|
exports.UrlString = UrlString;
|
|
9155
9253
|
exports.buildClientInfo = buildClientInfo;
|
|
9156
9254
|
exports.buildClientInfoFromHomeAccountId = buildClientInfoFromHomeAccountId;
|
|
9255
|
+
exports.invoke = invoke;
|
|
9256
|
+
exports.invokeAsync = invokeAsync;
|
|
9157
9257
|
exports.version = version;
|
|
9158
9258
|
//# sourceMappingURL=index.cjs.map
|