@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.
Files changed (295) hide show
  1. package/dist/account/AuthToken.d.ts +14 -17
  2. package/dist/account/AuthToken.d.ts.map +1 -1
  3. package/dist/account/AuthToken.mjs +48 -39
  4. package/dist/account/AuthToken.mjs.map +1 -1
  5. package/dist/account/CcsCredential.mjs +1 -1
  6. package/dist/account/CcsCredential.mjs.map +1 -1
  7. package/dist/account/ClientInfo.d.ts.map +1 -1
  8. package/dist/account/ClientInfo.mjs +3 -4
  9. package/dist/account/ClientInfo.mjs.map +1 -1
  10. package/dist/authority/Authority.d.ts +1 -0
  11. package/dist/authority/Authority.d.ts.map +1 -1
  12. package/dist/authority/Authority.mjs +4 -2
  13. package/dist/authority/Authority.mjs.map +1 -1
  14. package/dist/authority/AuthorityFactory.d.ts +1 -0
  15. package/dist/authority/AuthorityFactory.d.ts.map +1 -1
  16. package/dist/authority/AuthorityFactory.mjs +3 -3
  17. package/dist/authority/AuthorityFactory.mjs.map +1 -1
  18. package/dist/authority/AuthorityMetadata.mjs +1 -1
  19. package/dist/authority/AuthorityMetadata.mjs.map +1 -1
  20. package/dist/authority/AuthorityOptions.mjs +1 -1
  21. package/dist/authority/AuthorityOptions.mjs.map +1 -1
  22. package/dist/authority/AuthorityType.mjs +1 -1
  23. package/dist/authority/AuthorityType.mjs.map +1 -1
  24. package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs +1 -1
  25. package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs.map +1 -1
  26. package/dist/authority/CloudInstanceDiscoveryResponse.mjs +1 -1
  27. package/dist/authority/CloudInstanceDiscoveryResponse.mjs.map +1 -1
  28. package/dist/authority/OpenIdConfigResponse.mjs +1 -1
  29. package/dist/authority/OpenIdConfigResponse.mjs.map +1 -1
  30. package/dist/authority/ProtocolMode.mjs +1 -1
  31. package/dist/authority/ProtocolMode.mjs.map +1 -1
  32. package/dist/authority/RegionDiscovery.mjs +1 -1
  33. package/dist/authority/RegionDiscovery.mjs.map +1 -1
  34. package/dist/cache/CacheManager.d.ts +2 -0
  35. package/dist/cache/CacheManager.d.ts.map +1 -1
  36. package/dist/cache/CacheManager.mjs +7 -5
  37. package/dist/cache/CacheManager.mjs.map +1 -1
  38. package/dist/cache/entities/AccessTokenEntity.d.ts.map +1 -1
  39. package/dist/cache/entities/AccessTokenEntity.mjs +4 -7
  40. package/dist/cache/entities/AccessTokenEntity.mjs.map +1 -1
  41. package/dist/cache/entities/AccountEntity.d.ts +1 -0
  42. package/dist/cache/entities/AccountEntity.d.ts.map +1 -1
  43. package/dist/cache/entities/AccountEntity.mjs +3 -4
  44. package/dist/cache/entities/AccountEntity.mjs.map +1 -1
  45. package/dist/cache/entities/AppMetadataEntity.mjs +1 -1
  46. package/dist/cache/entities/AppMetadataEntity.mjs.map +1 -1
  47. package/dist/cache/entities/AuthorityMetadataEntity.d.ts +1 -0
  48. package/dist/cache/entities/AuthorityMetadataEntity.d.ts.map +1 -1
  49. package/dist/cache/entities/AuthorityMetadataEntity.mjs +2 -1
  50. package/dist/cache/entities/AuthorityMetadataEntity.mjs.map +1 -1
  51. package/dist/cache/entities/CacheRecord.d.ts +1 -0
  52. package/dist/cache/entities/CacheRecord.d.ts.map +1 -1
  53. package/dist/cache/entities/CacheRecord.mjs +2 -1
  54. package/dist/cache/entities/CacheRecord.mjs.map +1 -1
  55. package/dist/cache/entities/CredentialEntity.mjs +1 -1
  56. package/dist/cache/entities/CredentialEntity.mjs.map +1 -1
  57. package/dist/cache/entities/IdTokenEntity.mjs +1 -1
  58. package/dist/cache/entities/IdTokenEntity.mjs.map +1 -1
  59. package/dist/cache/entities/RefreshTokenEntity.mjs +1 -1
  60. package/dist/cache/entities/RefreshTokenEntity.mjs.map +1 -1
  61. package/dist/cache/entities/ServerTelemetryEntity.mjs +1 -1
  62. package/dist/cache/entities/ServerTelemetryEntity.mjs.map +1 -1
  63. package/dist/cache/entities/ThrottlingEntity.mjs +1 -1
  64. package/dist/cache/entities/ThrottlingEntity.mjs.map +1 -1
  65. package/dist/cache/persistence/TokenCacheContext.mjs +1 -1
  66. package/dist/cache/persistence/TokenCacheContext.mjs.map +1 -1
  67. package/dist/cache/utils/CacheTypes.d.ts +7 -0
  68. package/dist/cache/utils/CacheTypes.d.ts.map +1 -1
  69. package/dist/client/AuthorizationCodeClient.d.ts +1 -0
  70. package/dist/client/AuthorizationCodeClient.d.ts.map +1 -1
  71. package/dist/client/AuthorizationCodeClient.mjs +11 -39
  72. package/dist/client/AuthorizationCodeClient.mjs.map +1 -1
  73. package/dist/client/BaseClient.d.ts +2 -1
  74. package/dist/client/BaseClient.d.ts.map +1 -1
  75. package/dist/client/BaseClient.mjs +9 -2
  76. package/dist/client/BaseClient.mjs.map +1 -1
  77. package/dist/client/RefreshTokenClient.d.ts +1 -0
  78. package/dist/client/RefreshTokenClient.d.ts.map +1 -1
  79. package/dist/client/RefreshTokenClient.mjs +3 -11
  80. package/dist/client/RefreshTokenClient.mjs.map +1 -1
  81. package/dist/client/SilentFlowClient.d.ts +1 -0
  82. package/dist/client/SilentFlowClient.d.ts.map +1 -1
  83. package/dist/client/SilentFlowClient.mjs +8 -7
  84. package/dist/client/SilentFlowClient.mjs.map +1 -1
  85. package/dist/config/ClientConfiguration.d.ts +2 -0
  86. package/dist/config/ClientConfiguration.d.ts.map +1 -1
  87. package/dist/config/ClientConfiguration.mjs +1 -1
  88. package/dist/config/ClientConfiguration.mjs.map +1 -1
  89. package/dist/crypto/ICrypto.mjs +1 -1
  90. package/dist/crypto/ICrypto.mjs.map +1 -1
  91. package/dist/crypto/JoseHeader.d.ts +1 -0
  92. package/dist/crypto/JoseHeader.d.ts.map +1 -1
  93. package/dist/crypto/JoseHeader.mjs +2 -1
  94. package/dist/crypto/JoseHeader.mjs.map +1 -1
  95. package/dist/crypto/PopTokenGenerator.d.ts +1 -0
  96. package/dist/crypto/PopTokenGenerator.d.ts.map +1 -1
  97. package/dist/crypto/PopTokenGenerator.mjs +2 -1
  98. package/dist/crypto/PopTokenGenerator.mjs.map +1 -1
  99. package/dist/error/AuthError.mjs +1 -1
  100. package/dist/error/AuthError.mjs.map +1 -1
  101. package/dist/error/ClientAuthError.mjs +1 -1
  102. package/dist/error/ClientAuthError.mjs.map +1 -1
  103. package/dist/error/ClientConfigurationError.mjs +1 -1
  104. package/dist/error/ClientConfigurationError.mjs.map +1 -1
  105. package/dist/error/InteractionRequiredAuthError.mjs +1 -1
  106. package/dist/error/InteractionRequiredAuthError.mjs.map +1 -1
  107. package/dist/error/JoseHeaderError.mjs +1 -1
  108. package/dist/error/JoseHeaderError.mjs.map +1 -1
  109. package/dist/error/ServerError.mjs +1 -1
  110. package/dist/error/ServerError.mjs.map +1 -1
  111. package/dist/index.cjs +1926 -1826
  112. package/dist/index.cjs.map +1 -1
  113. package/dist/index.d.ts +4 -3
  114. package/dist/index.d.ts.map +1 -1
  115. package/dist/index.mjs +5 -3
  116. package/dist/index.mjs.map +1 -1
  117. package/dist/logger/Logger.d.ts.map +1 -1
  118. package/dist/logger/Logger.mjs +2 -12
  119. package/dist/logger/Logger.mjs.map +1 -1
  120. package/dist/network/INetworkModule.mjs +1 -1
  121. package/dist/network/INetworkModule.mjs.map +1 -1
  122. package/dist/network/NetworkManager.d.ts +1 -0
  123. package/dist/network/NetworkManager.d.ts.map +1 -1
  124. package/dist/network/NetworkManager.mjs +2 -1
  125. package/dist/network/NetworkManager.mjs.map +1 -1
  126. package/dist/network/ThrottlingUtils.d.ts +1 -0
  127. package/dist/network/ThrottlingUtils.d.ts.map +1 -1
  128. package/dist/network/ThrottlingUtils.mjs +2 -1
  129. package/dist/network/ThrottlingUtils.mjs.map +1 -1
  130. package/dist/packageMetadata.d.ts +1 -1
  131. package/dist/packageMetadata.mjs +2 -2
  132. package/dist/packageMetadata.mjs.map +1 -1
  133. package/dist/request/AuthenticationHeaderParser.mjs +1 -1
  134. package/dist/request/AuthenticationHeaderParser.mjs.map +1 -1
  135. package/dist/request/RequestParameterBuilder.d.ts +1 -0
  136. package/dist/request/RequestParameterBuilder.d.ts.map +1 -1
  137. package/dist/request/RequestParameterBuilder.mjs +7 -7
  138. package/dist/request/RequestParameterBuilder.mjs.map +1 -1
  139. package/dist/request/RequestValidator.d.ts.map +1 -1
  140. package/dist/request/RequestValidator.mjs +4 -6
  141. package/dist/request/RequestValidator.mjs.map +1 -1
  142. package/dist/request/ScopeSet.mjs +4 -4
  143. package/dist/request/ScopeSet.mjs.map +1 -1
  144. package/dist/response/AuthenticationResult.d.ts +3 -1
  145. package/dist/response/AuthenticationResult.d.ts.map +1 -1
  146. package/dist/response/ResponseHandler.d.ts +5 -3
  147. package/dist/response/ResponseHandler.d.ts.map +1 -1
  148. package/dist/response/ResponseHandler.mjs +58 -39
  149. package/dist/response/ResponseHandler.mjs.map +1 -1
  150. package/dist/response/ServerAuthorizationTokenResponse.d.ts +2 -0
  151. package/dist/response/ServerAuthorizationTokenResponse.d.ts.map +1 -1
  152. package/dist/telemetry/performance/IPerformanceClient.d.ts +4 -4
  153. package/dist/telemetry/performance/IPerformanceClient.d.ts.map +1 -1
  154. package/dist/telemetry/performance/PerformanceClient.d.ts +2 -2
  155. package/dist/telemetry/performance/PerformanceClient.d.ts.map +1 -1
  156. package/dist/telemetry/performance/PerformanceClient.mjs +1 -1
  157. package/dist/telemetry/performance/PerformanceClient.mjs.map +1 -1
  158. package/dist/telemetry/performance/PerformanceEvent.d.ts +8 -1
  159. package/dist/telemetry/performance/PerformanceEvent.d.ts.map +1 -1
  160. package/dist/telemetry/performance/PerformanceEvent.mjs +9 -1
  161. package/dist/telemetry/performance/PerformanceEvent.mjs.map +1 -1
  162. package/dist/telemetry/performance/StubPerformanceClient.d.ts +3 -3
  163. package/dist/telemetry/performance/StubPerformanceClient.d.ts.map +1 -1
  164. package/dist/telemetry/performance/StubPerformanceClient.mjs +23 -3
  165. package/dist/telemetry/performance/StubPerformanceClient.mjs.map +1 -1
  166. package/dist/telemetry/server/ServerTelemetryManager.d.ts +1 -0
  167. package/dist/telemetry/server/ServerTelemetryManager.d.ts.map +1 -1
  168. package/dist/telemetry/server/ServerTelemetryManager.mjs +4 -4
  169. package/dist/telemetry/server/ServerTelemetryManager.mjs.map +1 -1
  170. package/dist/url/UrlString.d.ts.map +1 -1
  171. package/dist/url/UrlString.mjs +10 -12
  172. package/dist/url/UrlString.mjs.map +1 -1
  173. package/dist/utils/Constants.d.ts +10 -0
  174. package/dist/utils/Constants.d.ts.map +1 -1
  175. package/dist/utils/Constants.mjs +11 -2
  176. package/dist/utils/Constants.mjs.map +1 -1
  177. package/dist/utils/FunctionWrappers.d.ts +28 -0
  178. package/dist/utils/FunctionWrappers.d.ts.map +1 -0
  179. package/dist/utils/FunctionWrappers.mjs +90 -0
  180. package/dist/utils/FunctionWrappers.mjs.map +1 -0
  181. package/dist/utils/ProtocolUtils.d.ts.map +1 -1
  182. package/dist/utils/ProtocolUtils.mjs +4 -7
  183. package/dist/utils/ProtocolUtils.mjs.map +1 -1
  184. package/dist/utils/StringUtils.d.ts +0 -13
  185. package/dist/utils/StringUtils.d.ts.map +1 -1
  186. package/dist/utils/StringUtils.mjs +3 -34
  187. package/dist/utils/StringUtils.mjs.map +1 -1
  188. package/dist/utils/TimeUtils.mjs +1 -1
  189. package/dist/utils/TimeUtils.mjs.map +1 -1
  190. package/package.json +6 -4
  191. package/src/account/AccountInfo.ts +44 -0
  192. package/src/account/AuthToken.ts +70 -0
  193. package/src/account/CcsCredential.ts +16 -0
  194. package/src/account/ClientCredentials.ts +20 -0
  195. package/src/account/ClientInfo.ts +64 -0
  196. package/src/account/TokenClaims.ts +70 -0
  197. package/src/authority/Authority.ts +1225 -0
  198. package/src/authority/AuthorityFactory.ts +106 -0
  199. package/src/authority/AuthorityMetadata.ts +953 -0
  200. package/src/authority/AuthorityOptions.ts +40 -0
  201. package/src/authority/AuthorityType.ts +15 -0
  202. package/src/authority/AzureRegion.ts +7 -0
  203. package/src/authority/AzureRegionConfiguration.ts +16 -0
  204. package/src/authority/CloudDiscoveryMetadata.ts +10 -0
  205. package/src/authority/CloudInstanceDiscoveryErrorResponse.ts +26 -0
  206. package/src/authority/CloudInstanceDiscoveryResponse.ts +21 -0
  207. package/src/authority/ImdsOptions.ts +10 -0
  208. package/src/authority/OIDCOptions.ts +14 -0
  209. package/src/authority/OpenIdConfigResponse.ts +24 -0
  210. package/src/authority/ProtocolMode.ts +13 -0
  211. package/src/authority/RegionDiscovery.ts +193 -0
  212. package/src/authority/RegionDiscoveryMetadata.ts +15 -0
  213. package/src/broker/nativeBroker/INativeBrokerPlugin.ts +29 -0
  214. package/src/cache/CacheManager.ts +1619 -0
  215. package/src/cache/entities/AccessTokenEntity.ts +162 -0
  216. package/src/cache/entities/AccountEntity.ts +309 -0
  217. package/src/cache/entities/AppMetadataEntity.ts +91 -0
  218. package/src/cache/entities/AuthorityMetadataEntity.ts +112 -0
  219. package/src/cache/entities/CacheRecord.ts +33 -0
  220. package/src/cache/entities/CredentialEntity.ts +215 -0
  221. package/src/cache/entities/IdTokenEntity.ts +74 -0
  222. package/src/cache/entities/RefreshTokenEntity.ts +78 -0
  223. package/src/cache/entities/ServerTelemetryEntity.ts +38 -0
  224. package/src/cache/entities/ThrottlingEntity.ts +36 -0
  225. package/src/cache/interface/ICacheManager.ts +218 -0
  226. package/src/cache/interface/ICachePlugin.ts +11 -0
  227. package/src/cache/interface/ISerializableTokenCache.ts +9 -0
  228. package/src/cache/persistence/TokenCacheContext.ts +39 -0
  229. package/src/cache/utils/CacheTypes.ts +93 -0
  230. package/src/client/AuthorizationCodeClient.ts +714 -0
  231. package/src/client/BaseClient.ts +205 -0
  232. package/src/client/RefreshTokenClient.ts +442 -0
  233. package/src/client/SilentFlowClient.ts +186 -0
  234. package/src/config/AppTokenProvider.ts +47 -0
  235. package/src/config/ClientConfiguration.ts +287 -0
  236. package/src/crypto/ICrypto.ts +127 -0
  237. package/src/crypto/IGuidGenerator.ts +9 -0
  238. package/src/crypto/JoseHeader.ts +55 -0
  239. package/src/crypto/PopTokenGenerator.ts +155 -0
  240. package/src/crypto/SignedHttpRequest.ts +16 -0
  241. package/src/error/AuthError.ts +85 -0
  242. package/src/error/ClientAuthError.ts +738 -0
  243. package/src/error/ClientConfigurationError.ts +396 -0
  244. package/src/error/InteractionRequiredAuthError.ts +134 -0
  245. package/src/error/JoseHeaderError.ts +52 -0
  246. package/src/error/ServerError.ts +18 -0
  247. package/src/index.ts +215 -0
  248. package/src/logger/Logger.ts +272 -0
  249. package/src/network/INetworkModule.ts +57 -0
  250. package/src/network/NetworkManager.ts +76 -0
  251. package/src/network/RequestThumbprint.ts +22 -0
  252. package/src/network/ThrottlingUtils.ts +156 -0
  253. package/src/packageMetadata.ts +3 -0
  254. package/src/request/AuthenticationHeaderParser.ts +89 -0
  255. package/src/request/BaseAuthRequest.ts +46 -0
  256. package/src/request/CommonAuthorizationCodeRequest.ts +33 -0
  257. package/src/request/CommonAuthorizationUrlRequest.ts +56 -0
  258. package/src/request/CommonClientCredentialRequest.ts +23 -0
  259. package/src/request/CommonDeviceCodeRequest.ts +31 -0
  260. package/src/request/CommonEndSessionRequest.ts +27 -0
  261. package/src/request/CommonOnBehalfOfRequest.ts +19 -0
  262. package/src/request/CommonRefreshTokenRequest.ts +25 -0
  263. package/src/request/CommonSilentFlowRequest.ts +24 -0
  264. package/src/request/CommonUsernamePasswordRequest.ts +23 -0
  265. package/src/request/NativeRequest.ts +25 -0
  266. package/src/request/NativeSignOutRequest.ts +10 -0
  267. package/src/request/RequestParameterBuilder.ts +606 -0
  268. package/src/request/RequestValidator.ts +103 -0
  269. package/src/request/ScopeSet.ts +230 -0
  270. package/src/request/StoreInCache.ts +16 -0
  271. package/src/response/AuthenticationResult.ts +47 -0
  272. package/src/response/AuthorizationCodePayload.ts +18 -0
  273. package/src/response/DeviceCodeResponse.ts +31 -0
  274. package/src/response/ExternalTokenResponse.ts +24 -0
  275. package/src/response/IMDSBadResponse.ts +9 -0
  276. package/src/response/ResponseHandler.ts +614 -0
  277. package/src/response/ServerAuthorizationCodeResponse.ts +33 -0
  278. package/src/response/ServerAuthorizationTokenResponse.ts +54 -0
  279. package/src/telemetry/performance/IPerformanceClient.ts +71 -0
  280. package/src/telemetry/performance/IPerformanceMeasurement.ts +10 -0
  281. package/src/telemetry/performance/PerformanceClient.ts +635 -0
  282. package/src/telemetry/performance/PerformanceEvent.ts +542 -0
  283. package/src/telemetry/performance/StubPerformanceClient.ts +101 -0
  284. package/src/telemetry/server/ServerTelemetryManager.ts +274 -0
  285. package/src/telemetry/server/ServerTelemetryRequest.ts +13 -0
  286. package/src/url/IUri.ts +17 -0
  287. package/src/url/UrlString.ts +363 -0
  288. package/src/utils/Constants.ts +436 -0
  289. package/src/utils/FunctionWrappers.ts +105 -0
  290. package/src/utils/MsalTypes.ts +9 -0
  291. package/src/utils/ProtocolUtils.ts +124 -0
  292. package/src/utils/StringUtils.ts +106 -0
  293. package/src/utils/TimeUtils.ts +51 -0
  294. package/dist/account/DecodedAuthToken.d.ts +0 -9
  295. 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 2023-08-11 */
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
- * @hidden
1206
+ * ClientConfigurationErrorMessage class containing string constants used by error codes and messages.
986
1207
  */
987
- class StringUtils {
988
- /**
989
- * decode a JWT
990
- *
991
- * @param authToken
992
- */
993
- static decodeAuthToken(authToken) {
994
- if (StringUtils.isEmpty(authToken)) {
995
- throw ClientAuthError.createTokenNullOrEmptyError(authToken);
996
- }
997
- const tokenPartsRegex = /^([^\.\s]*)\.([^\.\s]+)\.([^\.\s]*)$/;
998
- const matches = tokenPartsRegex.exec(authToken);
999
- if (!matches || matches.length < 4) {
1000
- throw ClientAuthError.createTokenParsingError(`Given token is malformed: ${JSON.stringify(authToken)}`);
1001
- }
1002
- const crackedToken = {
1003
- header: matches[1],
1004
- JWSPayload: matches[2],
1005
- JWSSig: matches[3],
1006
- };
1007
- return crackedToken;
1008
- }
1009
- /**
1010
- * Check if a string is empty.
1011
- *
1012
- * @param str
1013
- */
1014
- static isEmpty(str) {
1015
- return typeof str === "undefined" || !str || 0 === str.length;
1016
- }
1017
- /**
1018
- * Check if stringified object is empty
1019
- * @param strObj
1020
- */
1021
- static isEmptyObj(strObj) {
1022
- if (strObj && !StringUtils.isEmpty(strObj)) {
1023
- try {
1024
- const obj = JSON.parse(strObj);
1025
- return Object.keys(obj).length === 0;
1026
- }
1027
- catch (e) { }
1028
- }
1029
- return true;
1030
- }
1031
- static startsWith(str, search) {
1032
- return str.indexOf(search) === 0;
1033
- }
1034
- static endsWith(str, search) {
1035
- return (str.length >= search.length &&
1036
- str.lastIndexOf(search) === str.length - search.length);
1037
- }
1038
- /**
1039
- * Parses string into an object.
1040
- *
1041
- * @param query
1042
- */
1043
- static queryStringToObject(query) {
1044
- const obj = {};
1045
- const params = query.split("&");
1046
- const decode = (s) => decodeURIComponent(s.replace(/\+/g, " "));
1047
- params.forEach((pair) => {
1048
- if (pair.trim()) {
1049
- const [key, value] = pair.split(/=(.+)/g, 2); // Split on the first occurence of the '=' character
1050
- if (key && value) {
1051
- obj[decode(key)] = decode(value);
1052
- }
1053
- }
1054
- });
1055
- return obj;
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
- * Trims entries in an array.
1059
- *
1060
- * @param arr
1324
+ * Creates an error thrown when the redirect uri is empty (not set by caller)
1061
1325
  */
1062
- static trimArrayEntries(arr) {
1063
- return arr.map((entry) => entry.trim());
1326
+ static createRedirectUriEmptyError() {
1327
+ return new ClientConfigurationError(ClientConfigurationErrorMessage.redirectUriNotSet.code, ClientConfigurationErrorMessage.redirectUriNotSet.desc);
1064
1328
  }
1065
1329
  /**
1066
- * Removes empty strings from array
1067
- * @param arr
1330
+ * Creates an error thrown when the post-logout redirect uri is empty (not set by caller)
1068
1331
  */
1069
- static removeEmptyStringsFromArray(arr) {
1070
- return arr.filter((entry) => {
1071
- return !StringUtils.isEmpty(entry);
1072
- });
1332
+ static createPostLogoutRedirectUriEmptyError() {
1333
+ return new ClientConfigurationError(ClientConfigurationErrorMessage.postLogoutUriNotSet.code, ClientConfigurationErrorMessage.postLogoutUriNotSet.desc);
1073
1334
  }
1074
1335
  /**
1075
- * Attempts to parse a string into JSON
1076
- * @param str
1336
+ * Creates an error thrown when the claims request could not be successfully parsed
1077
1337
  */
1078
- static jsonParseHelper(str) {
1079
- try {
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
- * Tests if a given string matches a given pattern, with support for wildcards and queries.
1088
- * @param pattern Wildcard pattern to string match. Supports "*" for wildcards and "?" for queries
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 matchPattern(pattern, input) {
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
- static createDefaultLoggerOptions() {
1144
- return {
1145
- loggerCallback: () => {
1146
- // allow users to not set loggerCallback
1147
- },
1148
- piiLoggingEnabled: false,
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
- * Create new Logger with existing configurations.
1356
+ * Creates an error thrown if URL string is empty or null.
1357
+ * @param urlString
1154
1358
  */
1155
- clone(packageName, packageVersion, correlationId) {
1156
- return new Logger({
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
- * Log message with required options.
1363
+ * Error thrown when scopes are empty.
1364
+ * @param scopesValue
1165
1365
  */
1166
- logMessage(logMessage, options) {
1167
- if (options.logLevel > this.level ||
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
- * Execute callback with message.
1370
+ * Error thrown when client id scope is not provided as single scope.
1371
+ * @param inputScopes
1189
1372
  */
1190
- executeCallback(level, message, containsPii) {
1191
- if (this.localCallback) {
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
- * Logs error messages.
1377
+ * Error thrown when prompt is not an allowed type.
1378
+ * @param promptValue
1197
1379
  */
1198
- error(message, correlationId) {
1199
- this.logMessage(message, {
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
- * Logs error messages with PII.
1384
+ * Creates error thrown when claims parameter is not a stringified JSON object
1207
1385
  */
1208
- errorPii(message, correlationId) {
1209
- this.logMessage(message, {
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
- * Logs warning messages.
1390
+ * Throws error when token request is empty and nothing cached in storage.
1217
1391
  */
1218
- warning(message, correlationId) {
1219
- this.logMessage(message, {
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
- * Logs warning messages with PII.
1396
+ * Throws error when token request is empty and nothing cached in storage.
1227
1397
  */
1228
- warningPii(message, correlationId) {
1229
- this.logMessage(message, {
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
- * Logs info messages.
1402
+ * Throws error when an invalid code_challenge_method is passed by the user
1237
1403
  */
1238
- info(message, correlationId) {
1239
- this.logMessage(message, {
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
- * Logs info messages with PII.
1408
+ * Throws error when both params: code_challenge and code_challenge_method are not passed together
1247
1409
  */
1248
- infoPii(message, correlationId) {
1249
- this.logMessage(message, {
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
- * Logs verbose messages.
1414
+ * Throws an error when the user passes invalid cloudDiscoveryMetadata
1257
1415
  */
1258
- verbose(message, correlationId) {
1259
- this.logMessage(message, {
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
- * Logs verbose messages with PII.
1420
+ * Throws an error when the user passes invalid cloudDiscoveryMetadata
1267
1421
  */
1268
- verbosePii(message, correlationId) {
1269
- this.logMessage(message, {
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
- * Logs trace messages.
1426
+ * Throws error when provided authority is not a member of the trusted host list
1277
1427
  */
1278
- trace(message, correlationId) {
1279
- this.logMessage(message, {
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
- * Logs trace messages with PII.
1432
+ * Throws error when the AzureCloudInstance is set to an invalid value
1287
1433
  */
1288
- tracePii(message, correlationId) {
1289
- this.logMessage(message, {
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
- * Returns whether PII Logging is enabled or not.
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
- isPiiLoggingEnabled() {
1299
- return this.piiLoggingEnabled || false;
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
- const AzureCloudInstance = {
1312
- // AzureCloudInstance is not specified.
1313
- None: "none",
1314
- // Microsoft Azure public cloud
1315
- AzurePublic: "https://login.microsoftonline.com",
1316
- // Microsoft PPE
1317
- AzurePpe: "https://login.windows-ppe.net",
1318
- // Microsoft Chinese national/regional cloud
1319
- AzureChina: "https://login.chinacloudapi.cn",
1320
- // Microsoft German national/regional cloud ("Black Forest")
1321
- AzureGermany: "https://login.microsoftonline.de",
1322
- // US Government cloud
1323
- AzureUsGovernment: "https://login.microsoftonline.us",
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
- * ClientConfigurationErrorMessage class containing string constants used by error codes and messages.
1332
- */
1333
- const ClientConfigurationErrorMessage = {
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 ClientConfigurationError extends ClientAuthError {
1443
- constructor(errorCode, errorMessage) {
1444
- super(errorCode, errorMessage);
1445
- this.name = "ClientConfigurationError";
1446
- Object.setPrototypeOf(this, ClientConfigurationError.prototype);
1447
- }
1448
- /**
1449
- * Creates an error thrown when the redirect uri is empty (not set by caller)
1450
- */
1451
- static createRedirectUriEmptyError() {
1452
- return new ClientConfigurationError(ClientConfigurationErrorMessage.redirectUriNotSet.code, ClientConfigurationErrorMessage.redirectUriNotSet.desc);
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
- * Creates an error thrown when the post-logout redirect uri is empty (not set by caller)
1601
+ * Factory method to create ScopeSet from space-delimited string
1602
+ * @param inputScopeString
1603
+ * @param appClientId
1604
+ * @param scopesRequired
1456
1605
  */
1457
- static createPostLogoutRedirectUriEmptyError() {
1458
- return new ClientConfigurationError(ClientConfigurationErrorMessage.postLogoutUriNotSet.code, ClientConfigurationErrorMessage.postLogoutUriNotSet.desc);
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 an error thrown when the claims request could not be successfully parsed
1612
+ * Creates the set of scopes to search for in cache lookups
1613
+ * @param inputScopeString
1614
+ * @returns
1462
1615
  */
1463
- static createClaimsRequestParsingError(claimsRequestParseError) {
1464
- return new ClientConfigurationError(ClientConfigurationErrorMessage.claimsRequestParsingError.code, `${ClientConfigurationErrorMessage.claimsRequestParsingError.desc} Given value: ${claimsRequestParseError}`);
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
- * Creates an error thrown if authority uri is given an insecure protocol.
1468
- * @param urlString
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
- static createInsecureAuthorityUriError(urlString) {
1471
- return new ClientConfigurationError(ClientConfigurationErrorMessage.authorityUriInsecure.code, `${ClientConfigurationErrorMessage.authorityUriInsecure.desc} Given URI: ${urlString}`);
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
- * Creates an error thrown if URL string does not parse into separate segments.
1475
- * @param urlString
1638
+ * Check if a given scope is present in this set of scopes.
1639
+ * @param scope
1476
1640
  */
1477
- static createUrlParseError(urlParseError) {
1478
- return new ClientConfigurationError(ClientConfigurationErrorMessage.urlParseError.code, `${ClientConfigurationErrorMessage.urlParseError.desc} Given Error: ${urlParseError}`);
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
- * Creates an error thrown if URL string is empty or null.
1482
- * @param urlString
1650
+ * Check if a set of scopes is present in this set of scopes.
1651
+ * @param scopeSet
1483
1652
  */
1484
- static createUrlEmptyError() {
1485
- return new ClientConfigurationError(ClientConfigurationErrorMessage.urlEmptyError.code, ClientConfigurationErrorMessage.urlEmptyError.desc);
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
- * Error thrown when scopes are empty.
1489
- * @param scopesValue
1661
+ * Check if set of scopes contains only the defaults
1490
1662
  */
1491
- static createEmptyScopesArrayError() {
1492
- return new ClientConfigurationError(ClientConfigurationErrorMessage.emptyScopesError.code, `${ClientConfigurationErrorMessage.emptyScopesError.desc}`);
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
- * Error thrown when client id scope is not provided as single scope.
1496
- * @param inputScopes
1673
+ * Appends single scope if passed
1674
+ * @param newScope
1497
1675
  */
1498
- static createClientIdSingleScopeError(inputScopes) {
1499
- return new ClientConfigurationError(ClientConfigurationErrorMessage.clientIdSingleScopeError.code, `${ClientConfigurationErrorMessage.clientIdSingleScopeError.desc} Given Scopes: ${inputScopes}`);
1676
+ appendScope(newScope) {
1677
+ if (newScope) {
1678
+ this.scopes.add(newScope.trim());
1679
+ }
1500
1680
  }
1501
1681
  /**
1502
- * Error thrown when prompt is not an allowed type.
1503
- * @param promptValue
1682
+ * Appends multiple scopes if passed
1683
+ * @param newScopes
1504
1684
  */
1505
- static createInvalidPromptError(promptValue) {
1506
- return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidPrompt.code, `${ClientConfigurationErrorMessage.invalidPrompt.desc} Given value: ${promptValue}`);
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
- * Creates error thrown when claims parameter is not a stringified JSON object
1694
+ * Removes element from set of scopes.
1695
+ * @param scope
1510
1696
  */
1511
- static createInvalidClaimsRequestError() {
1512
- return new ClientConfigurationError(ClientConfigurationErrorMessage.invalidClaimsRequest.code, ClientConfigurationErrorMessage.invalidClaimsRequest.desc);
1697
+ removeScope(scope) {
1698
+ if (!scope) {
1699
+ throw ClientAuthError.createRemoveEmptyScopeFromSetError(scope);
1700
+ }
1701
+ this.scopes.delete(scope.trim());
1513
1702
  }
1514
1703
  /**
1515
- * Throws error when token request is empty and nothing cached in storage.
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
- static createEmptyLogoutRequestError() {
1518
- return new ClientConfigurationError(ClientConfigurationErrorMessage.logoutRequestEmptyError.code, ClientConfigurationErrorMessage.logoutRequestEmptyError.desc);
1707
+ removeOIDCScopes() {
1708
+ OIDC_SCOPES.forEach((defaultScope) => {
1709
+ this.scopes.delete(defaultScope);
1710
+ });
1519
1711
  }
1520
1712
  /**
1521
- * Throws error when token request is empty and nothing cached in storage.
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 (StringUtils.isEmpty(rawClientInfo)) {
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 (StringUtils.isEmpty(homeAccountId)) {
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 (!StringUtils.isEmpty(clientInfo.uid) &&
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
- * JWT Token representation class. Parses token string and generates claims object.
2065
+ * Extract token by decoding the rawToken
2066
+ *
2067
+ * @param encodedToken
2095
2068
  */
2096
- class AuthToken {
2097
- constructor(rawToken, crypto) {
2098
- if (StringUtils.isEmpty(rawToken)) {
2099
- throw ClientAuthError.createTokenNullOrEmptyError(rawToken);
2100
- }
2101
- this.rawToken = rawToken;
2102
- this.claims = AuthToken.extractTokenClaims(rawToken, crypto);
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
- * Extract token by decoding the rawToken
2106
- *
2107
- * @param encodedToken
2108
- */
2109
- static extractTokenClaims(encodedToken, crypto) {
2110
- const decodedToken = StringUtils.decodeAuthToken(encodedToken);
2111
- // token will be decoded to get the username
2112
- try {
2113
- const base64TokenPayload = decodedToken.JWSPayload;
2114
- // base64Decode() should throw an error if there is an issue
2115
- const base64Decoded = crypto.base64Decode(base64TokenPayload);
2116
- return JSON.parse(base64Decoded);
2117
- }
2118
- catch (err) {
2119
- throw ClientAuthError.createTokenParsingError(err);
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
- * Determine if the token's max_age has transpired
2096
+ * const crackedToken = {
2097
+ * header: matches[1],
2098
+ * JWSPayload: matches[2],
2099
+ * JWSSig: matches[3],
2100
+ * };
2124
2101
  */
2125
- static checkMaxAge(authTime, maxAge) {
2126
- /*
2127
- * per https://openid.net/specs/openid-connect-core-1_0.html#AuthRequest
2128
- * To force an immediate re-authentication: If an app requires that a user re-authenticate prior to access,
2129
- * provide a value of 0 for the max_age parameter and the AS will force a fresh login.
2130
- */
2131
- const fiveMinuteSkew = 300000; // five minutes in milliseconds
2132
- if (maxAge === 0 || Date.now() - fiveMinuteSkew > authTime + maxAge) {
2133
- throw ClientAuthError.createMaxAgeTranspiredError();
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 = new AuthToken(idToken.secret, this.cryptoImpl).claims;
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 = new AuthToken(cachedIdToken.secret, this.cryptoImpl).claims;
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 (StringUtils.isEmpty(redirectUri)) {
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 (StringUtils.isEmpty(codeChallenge) ||
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((value, key) => {
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 (!StringUtils.isEmpty(state)) {
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 (!StringUtils.isEmpty(clientAssertion)) {
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 (!StringUtils.isEmpty(clientAssertionType)) {
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 (!StringUtils.isEmpty(cnfString)) {
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 (!StringUtils.isEmpty(sshJwkString)) {
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
- * Base application class which will construct requests to send to and handle responses from the Microsoft STS using the authorization code flow.
3873
+ * Enumeration of operations that are instrumented by have their performance measured by the PerformanceClient.
3874
+ *
3875
+ * @export
3876
+ * @enum {number}
3882
3877
  */
3883
- class BaseClient {
3884
- constructor(configuration, performanceClient) {
3885
- // Set the configuration
3886
- this.config = buildClientConfiguration(configuration);
3887
- // Initialize the logger
3888
- this.logger = new Logger(this.config.loggerOptions, name, version);
3889
- // Initialize crypto
3890
- this.cryptoUtils = this.config.cryptoInterface;
3891
- // Initialize storage interface
3892
- this.cacheManager = this.config.storageInterface;
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
- * Appends user state with random guid, or returns random guid.
4484
- * @param userState
4485
- * @param randomGuid
4158
+ * Http post to token endpoint
4159
+ * @param tokenEndpoint
4160
+ * @param queryString
4161
+ * @param headers
4162
+ * @param thumbprint
4486
4163
  */
4487
- static setRequestState(cryptoObj, userState, meta) {
4488
- const libraryState = ProtocolUtils.generateLibraryState(cryptoObj, meta);
4489
- return !StringUtils.isEmpty(userState)
4490
- ? `${libraryState}${Constants.RESOURCE_DELIM}${userState}`
4491
- : libraryState;
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
- * Generates the state value used by the common library.
4495
- * @param randomGuid
4496
- * @param cryptoObj
4180
+ * Updates the authority object of the client. Endpoint discovery must be completed.
4181
+ * @param updatedAuthority
4497
4182
  */
4498
- static generateLibraryState(cryptoObj, meta) {
4499
- if (!cryptoObj) {
4500
- throw ClientAuthError.createNoCryptoObjectError("generateLibraryState");
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
- const stateString = JSON.stringify(stateObj);
4510
- return cryptoObj.base64Encode(stateString);
4187
+ this.authority = updatedAuthority;
4511
4188
  }
4512
4189
  /**
4513
- * Parses the state into the RequestStateObject, which contains the LibraryState info and the state passed by the user.
4514
- * @param state
4515
- * @param cryptoObj
4190
+ * Creates query string for the /token request
4191
+ * @param request
4516
4192
  */
4517
- static parseRequestState(cryptoObj, state) {
4518
- if (!cryptoObj) {
4519
- throw ClientAuthError.createNoCryptoObjectError("parseRequestState");
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
- * Url object class which can perform various transformations on url strings.
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 UrlString {
4554
- get urlString() {
4555
- return this._urlString;
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
- constructor(url) {
4558
- this._urlString = url;
4559
- if (StringUtils.isEmpty(this._urlString)) {
4560
- // Throws error if url is empty
4561
- throw ClientConfigurationError.createUrlEmptyError();
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
- * Ensure urls are lower case and end with a / character.
4569
- * @param url
4242
+ * Generate target key component as per schema: <target>
4570
4243
  */
4571
- static canonicalizeUri(url) {
4572
- if (url) {
4573
- let lowerCaseUrl = url.toLowerCase();
4574
- if (StringUtils.endsWith(lowerCaseUrl, "?")) {
4575
- lowerCaseUrl = lowerCaseUrl.slice(0, -1);
4576
- }
4577
- else if (StringUtils.endsWith(lowerCaseUrl, "?/")) {
4578
- lowerCaseUrl = lowerCaseUrl.slice(0, -2);
4579
- }
4580
- if (!StringUtils.endsWith(lowerCaseUrl, "/")) {
4581
- lowerCaseUrl += "/";
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
- * Throws if urlString passed is not a valid authority URI string.
4271
+ * generates credential key
4272
+ * <home_account_id*>-\<environment>-<credential_type>-<client_id>-<realm\*>-<target\*>-<scheme\*>
4589
4273
  */
4590
- validateAsUri() {
4591
- // Attempts to parse url for uri components
4592
- let components;
4593
- try {
4594
- components = this.getUrlComponents();
4595
- }
4596
- catch (e) {
4597
- throw ClientConfigurationError.createUrlParseError(e);
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
- * Given a url and a query string return the url with provided query string appended
4611
- * @param url
4612
- * @param queryString
4285
+ * generates Account Id for keys
4286
+ * @param homeAccountId
4287
+ * @param environment
4613
4288
  */
4614
- static appendQueryString(url, queryString) {
4615
- if (StringUtils.isEmpty(queryString)) {
4616
- return url;
4617
- }
4618
- return url.indexOf("?") < 0
4619
- ? `${url}?${queryString}`
4620
- : `${url}&${queryString}`;
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
- * Returns a url with the hash removed
4624
- * @param url
4362
+ * Create IdTokenEntity
4363
+ * @param homeAccountId
4364
+ * @param authenticationResult
4365
+ * @param clientId
4366
+ * @param authority
4625
4367
  */
4626
- static removeHashFromUrl(url) {
4627
- return UrlString.canonicalizeUri(url.split("#")[0]);
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
- * Given a url like https://a:b/common/d?e=f#g, and a tenantId, returns https://a:b/tenantId/d
4631
- * @param href The url
4632
- * @param tenantId The tenant id to replace
4379
+ * Validates an entity: checks for all expected params
4380
+ * @param entity
4633
4381
  */
4634
- replaceTenantPath(tenantId) {
4635
- const urlObject = this.getUrlComponents();
4636
- const pathArray = urlObject.PathSegments;
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 UrlString.constructAuthorityUriFromObject(urlObject);
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
- * Returns the anchor part(#) of the URL
4405
+ * return the current time in Unix time (seconds).
4647
4406
  */
4648
- getHash() {
4649
- return UrlString.parseHash(this.urlString);
4407
+ static nowSeconds() {
4408
+ // Date.getTime() returns in milliseconds.
4409
+ return Math.round(new Date().getTime() / 1000.0);
4650
4410
  }
4651
4411
  /**
4652
- * Parses out the components from a url string.
4653
- * @returns An object with the various components. Please cache this value insted of calling this multiple times on the same url.
4412
+ * check if a token is expired based on given UTC time in seconds.
4413
+ * @param expiresOn
4654
4414
  */
4655
- getUrlComponents() {
4656
- // https://gist.github.com/curtisz/11139b2cfcaef4a261e0
4657
- const regEx = RegExp("^(([^:/?#]+):)?(//([^/?#]*))?([^?#]*)(\\?([^#]*))?(#(.*))?");
4658
- // If url string does not match regEx, we throw an error
4659
- const match = this.urlString.match(regEx);
4660
- if (!match) {
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
- * Parses hash string from given string. Returns empty string if no hash symbol is found.
4700
- * @param hashString
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 parseHash(hashString) {
4703
- const hashIndex1 = hashString.indexOf("#");
4704
- const hashIndex2 = hashString.indexOf("#/");
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
- * Parses query string from given string. Returns empty string if no query symbol is found.
4715
- * @param queryString
4433
+ * Waits for t number of milliseconds
4434
+ * @param t number
4435
+ * @param value T
4716
4436
  */
4717
- static parseQueryString(queryString) {
4718
- const queryIndex1 = queryString.indexOf("?");
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
- * Parses query server response string from given string.
4730
- * Extract hash between '?code=' and '#' if trailing '# is present.
4731
- * Returns empty string if no query symbol is found.
4732
- * @param queryString
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 parseQueryServerResponse(queryString) {
4735
- const queryIndex1 = queryString.indexOf("?code");
4736
- const queryIndex2 = queryString.indexOf("/?code");
4737
- const hashIndex = queryString.indexOf("#");
4738
- if (queryIndex2 > -1 && hashIndex > -1) {
4739
- return queryString.substring(queryIndex2 + 2, hashIndex);
4740
- }
4741
- else if (queryIndex2 > -1) {
4742
- return queryString.substring(queryIndex2 + 2);
4743
- }
4744
- else if (queryIndex1 > -1 && hashIndex > -1) {
4745
- return queryString.substring(queryIndex1 + 1, hashIndex);
4746
- }
4747
- else if (queryIndex1 > -1) {
4748
- return queryString.substring(queryIndex1 + 1);
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
- return Constants.EMPTY_STRING;
4751
- }
4752
- static constructAuthorityUriFromObject(urlObject) {
4753
- return new UrlString(urlObject.Protocol +
4754
- "//" +
4755
- urlObject.HostNameAndPort +
4756
- "/" +
4757
- urlObject.PathSegments.join("/"));
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
- // Strip the # symbol if present
4768
- const parsedHash = UrlString.parseHash(hash);
4769
- // If # symbol was not present, above will return empty string, so give original hash value
4770
- const deserializedHash = StringUtils.queryStringToObject(StringUtils.isEmpty(parsedHash) ? hash : parsedHash);
4771
- // Check if deserialization didn't work
4772
- if (!deserializedHash) {
4773
- throw ClientAuthError.createHashNotDeserializedError(JSON.stringify(deserializedHash));
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 deserializedHash;
4529
+ return atEntity;
4776
4530
  }
4777
4531
  /**
4778
- * Returns URL query string as server auth code response object.
4532
+ * Validates an entity: checks for all expected params
4533
+ * @param entity
4779
4534
  */
4780
- static getDeserializedQueryString(query) {
4781
- // Check if given query is empty
4782
- if (StringUtils.isEmpty(query)) {
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 deserializedQueryString;
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
- * Returns either deserialized query string or deserialized hash, depending on the serverResponseType
4799
- * as a server auth code response object.
4577
+ * Create RefreshTokenEntity
4578
+ * @param homeAccountId
4579
+ * @param authenticationResult
4580
+ * @param clientId
4581
+ * @param authority
4800
4582
  */
4801
- static getDeserializedCodeResponse(serverResponseType, hashFragment) {
4802
- const hashUrlString = new UrlString(hashFragment);
4803
- let serverParams;
4804
- if (serverResponseType === ServerResponseType.QUERY) {
4805
- serverParams = UrlString.getDeserializedQueryString(hashFragment);
4806
- }
4807
- else {
4808
- serverParams = UrlString.getDeserializedHash(hashUrlString.getHash());
4809
- }
4810
- return serverParams;
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
- * Check if the hash of the URL string contains known properties
4596
+ * Validates an entity: checks for all expected params
4597
+ * @param entity
4814
4598
  */
4815
- static hashContainsKnownProperties(hash) {
4816
- if (StringUtils.isEmpty(hash) || hash.indexOf("=") < 0) {
4817
- // Hash doesn't contain key/value pairs
4599
+ static isRefreshTokenEntity(entity) {
4600
+ if (!entity) {
4818
4601
  return false;
4819
4602
  }
4820
- const parameters = UrlString.getDeserializedHash(hash);
4821
- return !!(parameters.code ||
4822
- parameters.error_description ||
4823
- parameters.error ||
4824
- parameters.state);
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
- * Enumeration of operations that are instrumented by have their performance measured by the PerformanceClient.
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 PerformanceEvents = {
4839
- /**
4840
- * acquireTokenByCode API (msal-browser and msal-node).
4841
- * Used to acquire tokens by trading an authorization code against the token endpoint.
4842
- */
4843
- AcquireTokenByCode: "acquireTokenByCode",
4844
- /**
4845
- * acquireTokenByRefreshToken API (msal-browser and msal-node).
4846
- * Used to renew an access token using a refresh token against the token endpoint.
4847
- */
4848
- AcquireTokenByRefreshToken: "acquireTokenByRefreshToken",
4849
- /**
4850
- * acquireTokenSilent API (msal-browser and msal-node).
4851
- * Used to silently acquire a new access token (from the cache or the network).
4852
- */
4853
- AcquireTokenSilent: "acquireTokenSilent",
4854
- /**
4855
- * acquireTokenSilentAsync (msal-browser).
4856
- * Internal API for acquireTokenSilent.
4857
- */
4858
- AcquireTokenSilentAsync: "acquireTokenSilentAsync",
4859
- /**
4860
- * acquireTokenPopup (msal-browser).
4861
- * Used to acquire a new access token interactively through pop ups
4862
- */
4863
- AcquireTokenPopup: "acquireTokenPopup",
4864
- /**
4865
- * getPublicKeyThumbprint API in CryptoOpts class (msal-browser).
4866
- * Used to generate a public/private keypair and generate a public key thumbprint for pop requests.
4867
- */
4868
- CryptoOptsGetPublicKeyThumbprint: "cryptoOptsGetPublicKeyThumbprint",
4869
- /**
4870
- * signJwt API in CryptoOpts class (msal-browser).
4871
- * Used to signed a pop token.
4872
- */
4873
- CryptoOptsSignJwt: "cryptoOptsSignJwt",
4874
- /**
4875
- * acquireToken API in the SilentCacheClient class (msal-browser).
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
- * Time taken for token acquisition by broker
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
- AcquireTokenByBroker: "acquireTokenByBroker",
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
- * Time spent on the network for refresh token acquisition
4677
+ * Creates an error thrown when the authorization code required for a token request is null or empty.
4927
4678
  */
4928
- RefreshTokenClientExecuteTokenRequest: "refreshTokenClientExecuteTokenRequest",
4679
+ static createNoTokensFoundError() {
4680
+ return new InteractionRequiredAuthError(InteractionRequiredAuthErrorMessage.noTokensFoundError.code, InteractionRequiredAuthErrorMessage.noTokensFoundError.desc);
4681
+ }
4929
4682
  /**
4930
- * Time taken for acquiring refresh token , records RT size
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
- RefreshTokenClientAcquireToken: "refreshTokenClientAcquireToken",
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
- * Time taken for acquiring cached refresh token
4715
+ * Appends user state with random guid, or returns random guid.
4716
+ * @param userState
4717
+ * @param randomGuid
4935
4718
  */
4936
- RefreshTokenClientAcquireTokenWithCachedRefreshToken: "refreshTokenClientAcquireTokenWithCachedRefreshToken",
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
- * acquireTokenByRefreshToken API in RefreshTokenClient (msal-common).
4726
+ * Generates the state value used by the common library.
4727
+ * @param randomGuid
4728
+ * @param cryptoObj
4939
4729
  */
4940
- RefreshTokenClientAcquireTokenByRefreshToken: "refreshTokenClientAcquireTokenByRefreshToken",
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
- * Helper function to create token request body in RefreshTokenClient (msal-common).
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
- RefreshTokenClientCreateTokenRequestBody: "refreshTokenClientCreateTokenRequestBody",
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
- * acquireTokenFromCache (msal-browser).
4947
- * Internal API for acquiring token from cache
4798
+ * Ensure urls are lower case and end with a / character.
4799
+ * @param url
4948
4800
  */
4949
- AcquireTokenFromCache: "acquireTokenFromCache",
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
- * acquireTokenBySilentIframe (msal-browser).
4952
- * Internal API for acquiring token by silent Iframe
4818
+ * Throws if urlString passed is not a valid authority URI string.
4953
4819
  */
4954
- AcquireTokenBySilentIframe: "acquireTokenBySilentIframe",
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
- * Internal API for initializing base request in BaseInteractionClient (msal-browser)
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
- InitializeBaseRequest: "initializeBaseRequest",
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
- * Internal API for initializing silent request in SilentCacheClient (msal-browser)
4853
+ * Returns a url with the hash removed
4854
+ * @param url
4961
4855
  */
4962
- InitializeSilentRequest: "initializeSilentRequest",
4963
- InitializeClientApplication: "initializeClientApplication",
4856
+ static removeHashFromUrl(url) {
4857
+ return UrlString.canonicalizeUri(url.split("#")[0]);
4858
+ }
4964
4859
  /**
4965
- * Helper function in SilentIframeClient class (msal-browser).
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
- SilentIframeClientTokenHelper: "silentIframeClientTokenHelper",
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
- * SilentHandler
4876
+ * Returns the anchor part(#) of the URL
4970
4877
  */
4971
- SilentHandlerInitiateAuthRequest: "silentHandlerInitiateAuthRequest",
4972
- SilentHandlerMonitorIframeForHash: "silentHandlerMonitorIframeForHash",
4973
- SilentHandlerLoadFrame: "silentHandlerLoadFrame",
4878
+ getHash() {
4879
+ return UrlString.parseHash(this.urlString);
4880
+ }
4974
4881
  /**
4975
- * Helper functions in StandardInteractionClient class (msal-browser)
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
- StandardInteractionClientCreateAuthCodeClient: "standardInteractionClientCreateAuthCodeClient",
4978
- StandardInteractionClientGetClientConfiguration: "standardInteractionClientGetClientConfiguration",
4979
- StandardInteractionClientInitializeAuthorizationRequest: "standardInteractionClientInitializeAuthorizationRequest",
4980
- StandardInteractionClientInitializeAuthorizationCodeRequest: "standardInteractionClientInitializeAuthorizationCodeRequest",
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
- * getAuthCodeUrl API (msal-browser and msal-node).
4929
+ * Parses hash string from given string. Returns empty string if no hash symbol is found.
4930
+ * @param hashString
4983
4931
  */
4984
- GetAuthCodeUrl: "getAuthCodeUrl",
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
- * Functions from InteractionHandler (msal-browser)
4944
+ * Parses query string from given string. Returns empty string if no query symbol is found.
4945
+ * @param queryString
4987
4946
  */
4988
- HandleCodeResponseFromServer: "handleCodeResponseFromServer",
4989
- HandleCodeResponseFromHash: "handleCodeResponseFromHash",
4990
- UpdateTokenEndpointAuthority: "updateTokenEndpointAuthority",
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
- * APIs in Authorization Code Client (msal-common)
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
- AuthClientAcquireToken: "authClientAcquireToken",
4995
- AuthClientExecuteTokenRequest: "authClientExecuteTokenRequest",
4996
- AuthClientCreateTokenRequestBody: "authClientCreateTokenRequestBody",
4997
- AuthClientCreateQueryString: "authClientCreateQueryString",
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
- * Generate functions in PopTokenGenerator (msal-common)
4990
+ * Returns URL hash as server auth code response object.
5000
4991
  */
5001
- PopTokenGenerateCnf: "popTokenGenerateCnf",
5002
- PopTokenGenerateKid: "popTokenGenerateKid",
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
- * handleServerTokenResponse API in ResponseHandler (msal-common)
5008
+ * Returns URL query string as server auth code response object.
5005
5009
  */
5006
- HandleServerTokenResponse: "handleServerTokenResponse",
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
- * Authority functions
5026
+ * Returns either deserialized query string or deserialized hash, depending on the serverResponseType
5027
+ * as a server auth code response object.
5009
5028
  */
5010
- AuthorityFactoryCreateDiscoveredInstance: "authorityFactoryCreateDiscoveredInstance",
5011
- AuthorityResolveEndpointsAsync: "authorityResolveEndpointsAsync",
5012
- AuthorityGetCloudDiscoveryMetadataFromNetwork: "authorityGetCloudDiscoveryMetadataFromNetwork",
5013
- AuthorityUpdateCloudDiscoveryMetadata: "authorityUpdateCloudDiscoveryMetadata",
5014
- AuthorityGetEndpointMetadataFromNetwork: "authorityGetEndpointMetadataFromNetwork",
5015
- AuthorityUpdateEndpointMetadata: "authorityUpdateEndpointMetadata",
5016
- AuthorityUpdateMetadataWithRegionalInformation: "authorityUpdateMetadataWithRegionalInformation",
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
- * Region Discovery functions
5041
+ * Check if the hash of the URL string contains known properties
5019
5042
  */
5020
- RegionDiscoveryDetectRegion: "regionDiscoveryDetectRegion",
5021
- RegionDiscoveryGetRegionFromIMDS: "regionDiscoveryGetRegionFromIMDS",
5022
- RegionDiscoveryGetCurrentVersion: "regionDiscoveryGetCurrentVersion",
5023
- AcquireTokenByCodeAsync: "acquireTokenByCodeAsync",
5024
- GetEndpointMetadataFromNetwork: "getEndpointMetadataFromNetwork",
5025
- GetCloudDiscoveryMetadataFromNetworkMeasurement: "getCloudDiscoveryMetadataFromNetworkMeasurement",
5026
- HandleRedirectPromiseMeasurement: "handleRedirectPromiseMeasurement",
5027
- UpdateCloudDiscoveryMetadataMeasurement: "updateCloudDiscoveryMetadataMeasurement",
5028
- UsernamePasswordClientAcquireToken: "usernamePasswordClientAcquireToken",
5029
- NativeMessageHandlerHandshake: "nativeMessageHandlerHandshake",
5030
- NativeGenerateAuthResult: "nativeGenerateAuthResult",
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
- const errString = `${serverResponse.error_codes} - [${serverResponse.timestamp}]: ${serverResponse.error_description} - Correlation ID: ${serverResponse.correlation_id} - Trace ID: ${serverResponse.trace_id}`;
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 idTokenObj;
5337
+ let idTokenClaims;
5315
5338
  if (serverTokenResponse.id_token) {
5316
- idTokenObj = new AuthToken(serverTokenResponse.id_token || Constants.EMPTY_STRING, this.cryptoObj);
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
- !StringUtils.isEmpty(authCodePayload.nonce)) {
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 = idTokenObj.claims.auth_time;
5348
+ const authTime = idTokenClaims.auth_time;
5327
5349
  if (!authTime) {
5328
5350
  throw ClientAuthError.createAuthTimeNotFoundError();
5329
5351
  }
5330
- AuthToken.checkMaxAge(authTime, request.maxAge);
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, idTokenObj?.claims);
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, idTokenObj, userAssertionHash, authCodePayload);
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, idTokenObj, requestStateObj, undefined, serverRequestId);
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, idTokenObj, requestStateObj, serverTokenResponse, serverRequestId);
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, idTokenObj, userAssertionHash, authCodePayload) {
5407
+ generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenClaims, userAssertionHash, authCodePayload) {
5386
5408
  const env = authority.getPreferredCache();
5387
- if (StringUtils.isEmpty(env)) {
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 (!StringUtils.isEmpty(serverTokenResponse.id_token) &&
5394
- !!idTokenObj) {
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: idTokenObj.claims,
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 (!StringUtils.isEmpty(serverTokenResponse.access_token)) {
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, idTokenObj
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 (!StringUtils.isEmpty(serverTokenResponse.refresh_token)) {
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 (!StringUtils.isEmpty(serverTokenResponse.foci)) {
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, idTokenObj, requestState, serverTokenResponse, requestId) {
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
- : Constants.EMPTY_STRING;
5505
+ : "";
5483
5506
  }
5484
- const uid = idTokenObj?.claims.oid ||
5485
- idTokenObj?.claims.sub ||
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: idTokenObj ? idTokenObj.rawToken : Constants.EMPTY_STRING,
5502
- idTokenClaims: idTokenObj ? idTokenObj.claims : {},
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.performanceClient?.setPreQueueTime(PerformanceEvents.AuthClientCreateQueryString, request.correlationId);
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
- if (!request || !request.code) {
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.performanceClient?.setPreQueueTime(PerformanceEvents.AuthClientExecuteTokenRequest, request.correlationId);
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
- this.performanceClient?.setPreQueueTime(PerformanceEvents.HandleServerTokenResponse, request.correlationId);
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 (!StringUtils.isEmpty(request.claims) ||
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 idTokenObj;
6358
+ let idTokenClaims;
6287
6359
  if (cacheRecord.idToken) {
6288
- idTokenObj = new AuthToken(cacheRecord.idToken.secret, this.config.cryptoInterface);
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 = idTokenObj?.claims.auth_time;
6364
+ const authTime = idTokenClaims?.auth_time;
6293
6365
  if (!authTime) {
6294
6366
  throw ClientAuthError.createAuthTimeNotFoundError();
6295
6367
  }
6296
- AuthToken.checkMaxAge(authTime, request.maxAge);
6368
+ checkMaxAge(authTime, request.maxAge);
6297
6369
  }
6298
- return await ResponseHandler.generateAuthenticationResult(this.cryptoUtils, this.authority, cacheRecord, true, request, idTokenObj);
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
- !this.isAliasOfKnownMicrosoftAuthority(canonicalAuthorityHost)) {
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 (StringUtils.isEmpty(authorityUrl)) {
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 (!StringUtils.isEmpty(error.subError)) {
8567
+ if (error.subError) {
8490
8568
  lastRequests.errors.push(error.subError);
8491
8569
  }
8492
- else if (!StringUtils.isEmpty(error.errorCode)) {
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 extends PerformanceClient {
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.IdToken = AuthToken;
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