@azure/msal-common 14.3.0 → 14.4.1-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (246) hide show
  1. package/dist/account/AccountInfo.d.ts +31 -31
  2. package/dist/account/AuthToken.d.ts +17 -17
  3. package/dist/account/AuthToken.mjs +58 -58
  4. package/dist/account/CcsCredential.d.ts +9 -9
  5. package/dist/account/CcsCredential.mjs +8 -8
  6. package/dist/account/ClientCredentials.d.ts +14 -14
  7. package/dist/account/ClientInfo.d.ts +19 -19
  8. package/dist/account/ClientInfo.mjs +37 -37
  9. package/dist/account/TokenClaims.d.ts +65 -65
  10. package/dist/authority/Authority.d.ts +249 -249
  11. package/dist/authority/Authority.d.ts.map +1 -1
  12. package/dist/authority/Authority.mjs +788 -789
  13. package/dist/authority/Authority.mjs.map +1 -1
  14. package/dist/authority/AuthorityFactory.d.ts +31 -31
  15. package/dist/authority/AuthorityFactory.mjs +47 -47
  16. package/dist/authority/AuthorityMetadata.d.ts +503 -503
  17. package/dist/authority/AuthorityMetadata.mjs +603 -603
  18. package/dist/authority/AuthorityOptions.d.ts +27 -27
  19. package/dist/authority/AuthorityOptions.mjs +18 -18
  20. package/dist/authority/AuthorityType.d.ts +10 -10
  21. package/dist/authority/AuthorityType.mjs +13 -13
  22. package/dist/authority/AzureRegion.d.ts +1 -1
  23. package/dist/authority/AzureRegionConfiguration.d.ts +5 -5
  24. package/dist/authority/CloudDiscoveryMetadata.d.ts +5 -5
  25. package/dist/authority/CloudInstanceDiscoveryErrorResponse.d.ts +13 -13
  26. package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs +8 -8
  27. package/dist/authority/CloudInstanceDiscoveryResponse.d.ts +9 -9
  28. package/dist/authority/CloudInstanceDiscoveryResponse.mjs +8 -8
  29. package/dist/authority/ImdsOptions.d.ts +5 -5
  30. package/dist/authority/OIDCOptions.d.ts +8 -8
  31. package/dist/authority/OpenIdConfigResponse.d.ts +11 -11
  32. package/dist/authority/OpenIdConfigResponse.mjs +10 -10
  33. package/dist/authority/ProtocolMode.d.ts +8 -8
  34. package/dist/authority/ProtocolMode.mjs +11 -11
  35. package/dist/authority/RegionDiscovery.d.ts +32 -32
  36. package/dist/authority/RegionDiscovery.mjs +106 -106
  37. package/dist/authority/RegionDiscoveryMetadata.d.ts +6 -6
  38. package/dist/broker/nativeBroker/INativeBrokerPlugin.d.ts +15 -15
  39. package/dist/cache/CacheManager.d.ts +485 -480
  40. package/dist/cache/CacheManager.d.ts.map +1 -1
  41. package/dist/cache/CacheManager.mjs +1102 -1089
  42. package/dist/cache/CacheManager.mjs.map +1 -1
  43. package/dist/cache/entities/AccessTokenEntity.d.ts +25 -25
  44. package/dist/cache/entities/AccountEntity.d.ts +101 -101
  45. package/dist/cache/entities/AccountEntity.mjs +218 -218
  46. package/dist/cache/entities/AppMetadataEntity.d.ts +39 -39
  47. package/dist/cache/entities/AppMetadataEntity.mjs +66 -66
  48. package/dist/cache/entities/AuthorityMetadataEntity.d.ts +48 -48
  49. package/dist/cache/entities/AuthorityMetadataEntity.mjs +78 -78
  50. package/dist/cache/entities/CacheRecord.d.ts +14 -14
  51. package/dist/cache/entities/CacheRecord.mjs +14 -14
  52. package/dist/cache/entities/CredentialEntity.d.ts +30 -30
  53. package/dist/cache/entities/IdTokenEntity.d.ts +8 -8
  54. package/dist/cache/entities/RefreshTokenEntity.d.ts +7 -5
  55. package/dist/cache/entities/RefreshTokenEntity.d.ts.map +1 -1
  56. package/dist/cache/entities/ServerTelemetryEntity.d.ts +5 -12
  57. package/dist/cache/entities/ServerTelemetryEntity.d.ts.map +1 -1
  58. package/dist/cache/entities/ThrottlingEntity.d.ts +13 -13
  59. package/dist/cache/entities/ThrottlingEntity.mjs +23 -23
  60. package/dist/cache/interface/ICacheManager.d.ts +166 -166
  61. package/dist/cache/interface/ICachePlugin.d.ts +5 -5
  62. package/dist/cache/interface/ISerializableTokenCache.d.ts +4 -4
  63. package/dist/cache/persistence/TokenCacheContext.d.ts +23 -23
  64. package/dist/cache/persistence/TokenCacheContext.mjs +25 -25
  65. package/dist/cache/utils/CacheHelpers.d.ts +64 -58
  66. package/dist/cache/utils/CacheHelpers.d.ts.map +1 -1
  67. package/dist/cache/utils/CacheHelpers.mjs +236 -217
  68. package/dist/cache/utils/CacheHelpers.mjs.map +1 -1
  69. package/dist/cache/utils/CacheTypes.d.ts +67 -67
  70. package/dist/client/AuthorizationCodeClient.d.ts +74 -73
  71. package/dist/client/AuthorizationCodeClient.d.ts.map +1 -1
  72. package/dist/client/AuthorizationCodeClient.mjs +402 -408
  73. package/dist/client/AuthorizationCodeClient.mjs.map +1 -1
  74. package/dist/client/BaseClient.d.ts +51 -51
  75. package/dist/client/BaseClient.mjs +100 -100
  76. package/dist/client/RefreshTokenClient.d.ts +35 -35
  77. package/dist/client/RefreshTokenClient.d.ts.map +1 -1
  78. package/dist/client/RefreshTokenClient.mjs +193 -187
  79. package/dist/client/RefreshTokenClient.mjs.map +1 -1
  80. package/dist/client/SilentFlowClient.d.ts +27 -27
  81. package/dist/client/SilentFlowClient.d.ts.map +1 -1
  82. package/dist/client/SilentFlowClient.mjs +118 -116
  83. package/dist/client/SilentFlowClient.mjs.map +1 -1
  84. package/dist/config/AppTokenProvider.d.ts +38 -38
  85. package/dist/config/ClientConfiguration.d.ts +150 -150
  86. package/dist/config/ClientConfiguration.mjs +97 -97
  87. package/dist/crypto/ICrypto.d.ts +58 -58
  88. package/dist/crypto/ICrypto.d.ts.map +1 -1
  89. package/dist/crypto/ICrypto.mjs +30 -30
  90. package/dist/crypto/ICrypto.mjs.map +1 -1
  91. package/dist/crypto/IGuidGenerator.d.ts +4 -4
  92. package/dist/crypto/JoseHeader.d.ts +22 -22
  93. package/dist/crypto/JoseHeader.d.ts.map +1 -1
  94. package/dist/crypto/JoseHeader.mjs +38 -38
  95. package/dist/crypto/JoseHeader.mjs.map +1 -1
  96. package/dist/crypto/PopTokenGenerator.d.ts +60 -60
  97. package/dist/crypto/PopTokenGenerator.d.ts.map +1 -1
  98. package/dist/crypto/PopTokenGenerator.mjs +82 -82
  99. package/dist/crypto/PopTokenGenerator.mjs.map +1 -1
  100. package/dist/crypto/SignedHttpRequest.d.ts +15 -11
  101. package/dist/crypto/SignedHttpRequest.d.ts.map +1 -1
  102. package/dist/error/AuthError.d.ts +44 -44
  103. package/dist/error/AuthError.mjs +46 -46
  104. package/dist/error/AuthErrorCodes.d.ts +5 -5
  105. package/dist/error/AuthErrorCodes.mjs +9 -9
  106. package/dist/error/ClientAuthError.d.ts +237 -237
  107. package/dist/error/ClientAuthError.mjs +249 -249
  108. package/dist/error/ClientAuthErrorCodes.d.ts +44 -44
  109. package/dist/error/ClientAuthErrorCodes.mjs +48 -48
  110. package/dist/error/ClientConfigurationError.d.ts +128 -128
  111. package/dist/error/ClientConfigurationError.mjs +135 -135
  112. package/dist/error/ClientConfigurationErrorCodes.d.ts +22 -22
  113. package/dist/error/ClientConfigurationErrorCodes.mjs +26 -26
  114. package/dist/error/InteractionRequiredAuthError.d.ts +57 -57
  115. package/dist/error/InteractionRequiredAuthError.d.ts.map +1 -1
  116. package/dist/error/InteractionRequiredAuthError.mjs +78 -77
  117. package/dist/error/InteractionRequiredAuthError.mjs.map +1 -1
  118. package/dist/error/InteractionRequiredAuthErrorCodes.d.ts +6 -5
  119. package/dist/error/InteractionRequiredAuthErrorCodes.d.ts.map +1 -1
  120. package/dist/error/InteractionRequiredAuthErrorCodes.mjs +13 -12
  121. package/dist/error/InteractionRequiredAuthErrorCodes.mjs.map +1 -1
  122. package/dist/error/JoseHeaderError.d.ts +15 -15
  123. package/dist/error/JoseHeaderError.mjs +22 -22
  124. package/dist/error/JoseHeaderErrorCodes.d.ts +2 -2
  125. package/dist/error/JoseHeaderErrorCodes.mjs +6 -6
  126. package/dist/error/ServerError.d.ts +7 -7
  127. package/dist/error/ServerError.mjs +14 -14
  128. package/dist/index.cjs +8300 -8350
  129. package/dist/index.cjs.map +1 -1
  130. package/dist/index.d.ts +98 -97
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.mjs +4 -3
  133. package/dist/index.mjs.map +1 -1
  134. package/dist/logger/Logger.d.ts +95 -95
  135. package/dist/logger/Logger.mjs +188 -188
  136. package/dist/network/INetworkModule.d.ts +29 -29
  137. package/dist/network/INetworkModule.mjs +12 -12
  138. package/dist/network/NetworkManager.d.ts +33 -33
  139. package/dist/network/NetworkManager.mjs +34 -34
  140. package/dist/network/RequestThumbprint.d.ts +18 -16
  141. package/dist/network/RequestThumbprint.d.ts.map +1 -1
  142. package/dist/network/ThrottlingUtils.d.ts +42 -42
  143. package/dist/network/ThrottlingUtils.mjs +95 -95
  144. package/dist/packageMetadata.d.ts +2 -2
  145. package/dist/packageMetadata.mjs +4 -4
  146. package/dist/request/AuthenticationHeaderParser.d.ts +19 -19
  147. package/dist/request/AuthenticationHeaderParser.mjs +55 -55
  148. package/dist/request/BaseAuthRequest.d.ts +43 -40
  149. package/dist/request/BaseAuthRequest.d.ts.map +1 -1
  150. package/dist/request/CommonAuthorizationCodeRequest.d.ts +27 -27
  151. package/dist/request/CommonAuthorizationUrlRequest.d.ts +50 -50
  152. package/dist/request/CommonClientCredentialRequest.d.ts +17 -17
  153. package/dist/request/CommonDeviceCodeRequest.d.ts +21 -21
  154. package/dist/request/CommonEndSessionRequest.d.ts +21 -21
  155. package/dist/request/CommonOnBehalfOfRequest.d.ts +13 -13
  156. package/dist/request/CommonRefreshTokenRequest.d.ts +23 -22
  157. package/dist/request/CommonRefreshTokenRequest.d.ts.map +1 -1
  158. package/dist/request/CommonSilentFlowRequest.d.ts +21 -20
  159. package/dist/request/CommonSilentFlowRequest.d.ts.map +1 -1
  160. package/dist/request/CommonUsernamePasswordRequest.d.ts +17 -17
  161. package/dist/request/NativeRequest.d.ts +19 -19
  162. package/dist/request/NativeSignOutRequest.d.ts +5 -5
  163. package/dist/request/RequestParameterBuilder.d.ts +217 -217
  164. package/dist/request/RequestParameterBuilder.mjs +381 -381
  165. package/dist/request/RequestValidator.d.ts +33 -33
  166. package/dist/request/RequestValidator.mjs +81 -81
  167. package/dist/request/ScopeSet.d.ts +88 -88
  168. package/dist/request/ScopeSet.mjs +197 -197
  169. package/dist/request/StoreInCache.d.ts +8 -8
  170. package/dist/response/AuthenticationResult.d.ts +41 -41
  171. package/dist/response/AuthorizationCodePayload.d.ts +13 -13
  172. package/dist/response/DeviceCodeResponse.d.ts +25 -25
  173. package/dist/response/ExternalTokenResponse.d.ts +15 -15
  174. package/dist/response/IMDSBadResponse.d.ts +4 -4
  175. package/dist/response/ResponseHandler.d.ts +67 -67
  176. package/dist/response/ResponseHandler.d.ts.map +1 -1
  177. package/dist/response/ResponseHandler.mjs +312 -312
  178. package/dist/response/ResponseHandler.mjs.map +1 -1
  179. package/dist/response/ServerAuthorizationCodeResponse.d.ts +25 -25
  180. package/dist/response/ServerAuthorizationTokenResponse.d.ts +46 -46
  181. package/dist/telemetry/performance/IPerformanceClient.d.ts +51 -51
  182. package/dist/telemetry/performance/IPerformanceMeasurement.d.ts +5 -5
  183. package/dist/telemetry/performance/PerformanceClient.d.ts +191 -191
  184. package/dist/telemetry/performance/PerformanceClient.mjs +409 -409
  185. package/dist/telemetry/performance/PerformanceEvent.d.ts +464 -457
  186. package/dist/telemetry/performance/PerformanceEvent.d.ts.map +1 -1
  187. package/dist/telemetry/performance/PerformanceEvent.mjs +253 -249
  188. package/dist/telemetry/performance/PerformanceEvent.mjs.map +1 -1
  189. package/dist/telemetry/performance/StubPerformanceClient.d.ts +24 -24
  190. package/dist/telemetry/performance/StubPerformanceClient.mjs +76 -76
  191. package/dist/telemetry/server/ServerTelemetryManager.d.ts +66 -66
  192. package/dist/telemetry/server/ServerTelemetryManager.d.ts.map +1 -1
  193. package/dist/telemetry/server/ServerTelemetryManager.mjs +201 -198
  194. package/dist/telemetry/server/ServerTelemetryManager.mjs.map +1 -1
  195. package/dist/telemetry/server/ServerTelemetryRequest.d.ts +8 -8
  196. package/dist/url/IUri.d.ts +12 -12
  197. package/dist/url/UrlString.d.ts +48 -83
  198. package/dist/url/UrlString.d.ts.map +1 -1
  199. package/dist/url/UrlString.mjs +163 -282
  200. package/dist/url/UrlString.mjs.map +1 -1
  201. package/dist/utils/Constants.d.ts +365 -366
  202. package/dist/utils/Constants.d.ts.map +1 -1
  203. package/dist/utils/Constants.mjs +376 -377
  204. package/dist/utils/Constants.mjs.map +1 -1
  205. package/dist/utils/FunctionWrappers.d.ts +27 -27
  206. package/dist/utils/FunctionWrappers.mjs +84 -84
  207. package/dist/utils/MsalTypes.d.ts +6 -6
  208. package/dist/utils/ProtocolUtils.d.ts +42 -42
  209. package/dist/utils/ProtocolUtils.mjs +69 -69
  210. package/dist/utils/StringUtils.d.ts +40 -40
  211. package/dist/utils/StringUtils.mjs +95 -95
  212. package/dist/utils/TimeUtils.d.ts +27 -27
  213. package/dist/utils/TimeUtils.mjs +45 -45
  214. package/dist/utils/UrlUtils.d.ts +11 -0
  215. package/dist/utils/UrlUtils.d.ts.map +1 -0
  216. package/dist/utils/UrlUtils.mjs +52 -0
  217. package/dist/utils/UrlUtils.mjs.map +1 -0
  218. package/package.json +92 -92
  219. package/src/authority/Authority.ts +2 -3
  220. package/src/cache/CacheManager.ts +63 -22
  221. package/src/cache/entities/RefreshTokenEntity.ts +3 -1
  222. package/src/cache/entities/ServerTelemetryEntity.ts +2 -30
  223. package/src/cache/utils/CacheHelpers.ts +27 -1
  224. package/src/client/AuthorizationCodeClient.ts +5 -14
  225. package/src/client/RefreshTokenClient.ts +20 -2
  226. package/src/client/SilentFlowClient.ts +8 -4
  227. package/src/crypto/ICrypto.ts +7 -2
  228. package/src/crypto/JoseHeader.ts +4 -4
  229. package/src/crypto/PopTokenGenerator.ts +2 -0
  230. package/src/crypto/SignedHttpRequest.ts +6 -0
  231. package/src/error/InteractionRequiredAuthError.ts +2 -0
  232. package/src/error/InteractionRequiredAuthErrorCodes.ts +1 -0
  233. package/src/index.ts +3 -1
  234. package/src/network/RequestThumbprint.ts +2 -0
  235. package/src/packageMetadata.ts +1 -1
  236. package/src/request/BaseAuthRequest.ts +3 -0
  237. package/src/request/CommonRefreshTokenRequest.ts +1 -0
  238. package/src/request/CommonSilentFlowRequest.ts +1 -0
  239. package/src/response/ResponseHandler.ts +8 -4
  240. package/src/telemetry/performance/PerformanceEvent.ts +12 -1
  241. package/src/telemetry/server/ServerTelemetryManager.ts +12 -6
  242. package/src/url/UrlString.ts +6 -153
  243. package/src/utils/Constants.ts +3 -3
  244. package/src/utils/UrlUtils.ts +60 -0
  245. package/dist/cache/entities/ServerTelemetryEntity.mjs +0 -34
  246. package/dist/cache/entities/ServerTelemetryEntity.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- /*! @azure/msal-common v14.3.0 2023-10-30 */
1
+ /*! @azure/msal-common v14.4.1-beta.0 2023-11-14 */
2
2
  'use strict';
3
3
  import { Separators, CredentialType, AuthenticationScheme, THE_FAMILY_ID, APP_METADATA, AUTHORITY_METADATA_CONSTANTS } from '../utils/Constants.mjs';
4
4
  import { generateCredentialKey } from './utils/CacheHelpers.mjs';
@@ -10,1094 +10,1107 @@ import { name, version } from '../packageMetadata.mjs';
10
10
  import { getAliasesFromStaticSources } from '../authority/AuthorityMetadata.mjs';
11
11
  import { invalidCacheRecord, bindingKeyNotRemoved, multipleMatchingAppMetadata, methodNotImplemented } from '../error/ClientAuthErrorCodes.mjs';
12
12
 
13
- /*
14
- * Copyright (c) Microsoft Corporation. All rights reserved.
15
- * Licensed under the MIT License.
16
- */
17
- /**
18
- * Interface class which implement cache storage functions used by MSAL to perform validity checks, and store tokens.
19
- * @internal
20
- */
21
- class CacheManager {
22
- constructor(clientId, cryptoImpl, logger, staticAuthorityOptions) {
23
- this.clientId = clientId;
24
- this.cryptoImpl = cryptoImpl;
25
- this.commonLogger = logger.clone(name, version);
26
- this.staticAuthorityOptions = staticAuthorityOptions;
27
- }
28
- /**
29
- * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.
30
- * @param accountFilter - (Optional) filter to narrow down the accounts returned
31
- * @returns Array of AccountInfo objects in cache
32
- */
33
- getAllAccounts(accountFilter) {
34
- const validAccounts = [];
35
- this.getAccountsFilteredBy(accountFilter || {}).forEach((accountEntity) => {
36
- const accountInfo = this.getAccountInfoFromEntity(accountEntity, accountFilter);
37
- if (accountInfo) {
38
- validAccounts.push(accountInfo);
39
- }
40
- });
41
- return validAccounts;
42
- }
43
- /**
44
- * Gets accountInfo object based on provided filters
45
- */
46
- getAccountInfoFilteredBy(accountFilter) {
47
- const allAccounts = this.getAllAccounts(accountFilter);
48
- if (allAccounts.length > 1) {
49
- // If one or more accounts are found, further filter to the first account that has an ID token
50
- return allAccounts.filter((account) => {
51
- return !!account.idTokenClaims;
52
- })[0];
53
- }
54
- else if (allAccounts.length === 1) {
55
- // If only one account is found, return it regardless of whether a matching ID token was found
56
- return allAccounts[0];
57
- }
58
- else {
59
- return null;
60
- }
61
- }
62
- /**
63
- * Returns a single matching
64
- * @param accountFilter
65
- * @returns
66
- */
67
- getBaseAccountInfo(accountFilter) {
68
- const accountEntities = this.getAccountsFilteredBy(accountFilter);
69
- if (accountEntities.length > 0) {
70
- return accountEntities[0].getAccountInfo();
71
- }
72
- else {
73
- return null;
74
- }
75
- }
76
- getAccountInfoFromEntity(accountEntity, accountFilter) {
77
- const accountInfo = accountEntity.getAccountInfo();
78
- const idToken = this.getIdToken(accountInfo);
79
- if (idToken) {
80
- const idTokenClaims = extractTokenClaims(idToken.secret, this.cryptoImpl.base64Decode);
81
- if (this.idTokenClaimsMatchAccountFilter(idTokenClaims, accountFilter)) {
82
- accountInfo.idToken = idToken.secret;
83
- accountInfo.idTokenClaims = idTokenClaims;
84
- return accountInfo;
85
- }
86
- }
87
- return accountInfo;
88
- }
89
- idTokenClaimsMatchAccountFilter(idTokenClaims, accountFilter) {
90
- if (accountFilter) {
91
- if (!!accountFilter.loginHint &&
92
- !this.matchLoginHint(idTokenClaims, accountFilter.loginHint)) {
93
- return false;
94
- }
95
- if (!!accountFilter.sid &&
96
- !this.matchSid(idTokenClaims, accountFilter.sid)) {
97
- return false;
98
- }
99
- }
100
- return true;
101
- }
102
- /**
103
- * saves a cache record
104
- * @param cacheRecord
105
- */
106
- async saveCacheRecord(cacheRecord, storeInCache) {
107
- if (!cacheRecord) {
108
- throw createClientAuthError(invalidCacheRecord);
109
- }
110
- if (!!cacheRecord.account) {
111
- this.setAccount(cacheRecord.account);
112
- }
113
- if (!!cacheRecord.idToken && storeInCache?.idToken !== false) {
114
- this.setIdTokenCredential(cacheRecord.idToken);
115
- }
116
- if (!!cacheRecord.accessToken && storeInCache?.accessToken !== false) {
117
- await this.saveAccessToken(cacheRecord.accessToken);
118
- }
119
- if (!!cacheRecord.refreshToken &&
120
- storeInCache?.refreshToken !== false) {
121
- this.setRefreshTokenCredential(cacheRecord.refreshToken);
122
- }
123
- if (!!cacheRecord.appMetadata) {
124
- this.setAppMetadata(cacheRecord.appMetadata);
125
- }
126
- }
127
- /**
128
- * saves access token credential
129
- * @param credential
130
- */
131
- async saveAccessToken(credential) {
132
- const accessTokenFilter = {
133
- clientId: credential.clientId,
134
- credentialType: credential.credentialType,
135
- environment: credential.environment,
136
- homeAccountId: credential.homeAccountId,
137
- realm: credential.realm,
138
- tokenType: credential.tokenType,
139
- requestedClaimsHash: credential.requestedClaimsHash,
140
- };
141
- const tokenKeys = this.getTokenKeys();
142
- const currentScopes = ScopeSet.fromString(credential.target);
143
- const removedAccessTokens = [];
144
- tokenKeys.accessToken.forEach((key) => {
145
- if (!this.accessTokenKeyMatchesFilter(key, accessTokenFilter, false)) {
146
- return;
147
- }
148
- const tokenEntity = this.getAccessTokenCredential(key);
149
- if (tokenEntity &&
150
- this.credentialMatchesFilter(tokenEntity, accessTokenFilter)) {
151
- const tokenScopeSet = ScopeSet.fromString(tokenEntity.target);
152
- if (tokenScopeSet.intersectingScopeSets(currentScopes)) {
153
- removedAccessTokens.push(this.removeAccessToken(key));
154
- }
155
- }
156
- });
157
- await Promise.all(removedAccessTokens);
158
- this.setAccessTokenCredential(credential);
159
- }
160
- /**
161
- * Retrieve accounts matching all provided filters; if no filter is set, get all accounts
162
- * Not checking for casing as keys are all generated in lower case, remember to convert to lower case if object properties are compared
163
- * @param accountFilter - An object containing Account properties to filter by
164
- */
165
- getAccountsFilteredBy(accountFilter) {
166
- const allAccountKeys = this.getAccountKeys();
167
- const matchingAccounts = [];
168
- allAccountKeys.forEach((cacheKey) => {
169
- if (!this.isAccountKey(cacheKey, accountFilter.homeAccountId, accountFilter.tenantId)) {
170
- // Don't parse value if the key doesn't match the account filters
171
- return;
172
- }
173
- const entity = this.getAccount(cacheKey);
174
- if (!entity) {
175
- return;
176
- }
177
- if (!!accountFilter.homeAccountId &&
178
- !this.matchHomeAccountId(entity, accountFilter.homeAccountId)) {
179
- return;
180
- }
181
- if (!!accountFilter.localAccountId &&
182
- !this.matchLocalAccountId(entity, accountFilter.localAccountId)) {
183
- return;
184
- }
185
- if (!!accountFilter.username &&
186
- !this.matchUsername(entity, accountFilter.username)) {
187
- return;
188
- }
189
- if (!!accountFilter.environment &&
190
- !this.matchEnvironment(entity, accountFilter.environment)) {
191
- return;
192
- }
193
- if (!!accountFilter.realm &&
194
- !this.matchRealm(entity, accountFilter.realm)) {
195
- return;
196
- }
197
- // tenantId is another name for realm
198
- if (!!accountFilter.tenantId &&
199
- !this.matchRealm(entity, accountFilter.tenantId)) {
200
- return;
201
- }
202
- if (!!accountFilter.nativeAccountId &&
203
- !this.matchNativeAccountId(entity, accountFilter.nativeAccountId)) {
204
- return;
205
- }
206
- if (!!accountFilter.authorityType &&
207
- !this.matchAuthorityType(entity, accountFilter.authorityType)) {
208
- return;
209
- }
210
- if (!!accountFilter.name &&
211
- !this.matchName(entity, accountFilter.name)) {
212
- return;
213
- }
214
- matchingAccounts.push(entity);
215
- });
216
- return matchingAccounts;
217
- }
218
- /**
219
- * Returns true if the given key matches our account key schema. Also matches homeAccountId and/or tenantId if provided
220
- * @param key
221
- * @param homeAccountId
222
- * @param tenantId
223
- * @returns
224
- */
225
- isAccountKey(key, homeAccountId, tenantId) {
226
- if (key.split(Separators.CACHE_KEY_SEPARATOR).length < 3) {
227
- // Account cache keys contain 3 items separated by '-' (each item may also contain '-')
228
- return false;
229
- }
230
- if (homeAccountId &&
231
- !key.toLowerCase().includes(homeAccountId.toLowerCase())) {
232
- return false;
233
- }
234
- if (tenantId && !key.toLowerCase().includes(tenantId.toLowerCase())) {
235
- return false;
236
- }
237
- // Do not check environment as aliasing can cause false negatives
238
- return true;
239
- }
240
- /**
241
- * Returns true if the given key matches our credential key schema.
242
- * @param key
243
- */
244
- isCredentialKey(key) {
245
- if (key.split(Separators.CACHE_KEY_SEPARATOR).length < 6) {
246
- // Credential cache keys contain 6 items separated by '-' (each item may also contain '-')
247
- return false;
248
- }
249
- const lowerCaseKey = key.toLowerCase();
250
- // Credential keys must indicate what credential type they represent
251
- if (lowerCaseKey.indexOf(CredentialType.ID_TOKEN.toLowerCase()) ===
252
- -1 &&
253
- lowerCaseKey.indexOf(CredentialType.ACCESS_TOKEN.toLowerCase()) ===
254
- -1 &&
255
- lowerCaseKey.indexOf(CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME.toLowerCase()) === -1 &&
256
- lowerCaseKey.indexOf(CredentialType.REFRESH_TOKEN.toLowerCase()) ===
257
- -1) {
258
- return false;
259
- }
260
- if (lowerCaseKey.indexOf(CredentialType.REFRESH_TOKEN.toLowerCase()) >
261
- -1) {
262
- // Refresh tokens must contain the client id or family id
263
- const clientIdValidation = `${CredentialType.REFRESH_TOKEN}${Separators.CACHE_KEY_SEPARATOR}${this.clientId}${Separators.CACHE_KEY_SEPARATOR}`;
264
- const familyIdValidation = `${CredentialType.REFRESH_TOKEN}${Separators.CACHE_KEY_SEPARATOR}${THE_FAMILY_ID}${Separators.CACHE_KEY_SEPARATOR}`;
265
- if (lowerCaseKey.indexOf(clientIdValidation.toLowerCase()) === -1 &&
266
- lowerCaseKey.indexOf(familyIdValidation.toLowerCase()) === -1) {
267
- return false;
268
- }
269
- }
270
- else if (lowerCaseKey.indexOf(this.clientId.toLowerCase()) === -1) {
271
- // Tokens must contain the clientId
272
- return false;
273
- }
274
- return true;
275
- }
276
- /**
277
- * Returns whether or not the given credential entity matches the filter
278
- * @param entity
279
- * @param filter
280
- * @returns
281
- */
282
- credentialMatchesFilter(entity, filter) {
283
- if (!!filter.clientId && !this.matchClientId(entity, filter.clientId)) {
284
- return false;
285
- }
286
- if (!!filter.userAssertionHash &&
287
- !this.matchUserAssertionHash(entity, filter.userAssertionHash)) {
288
- return false;
289
- }
290
- /*
291
- * homeAccountId can be undefined, and we want to filter out cached items that have a homeAccountId of ""
292
- * because we don't want a client_credential request to return a cached token that has a homeAccountId
293
- */
294
- if (typeof filter.homeAccountId === "string" &&
295
- !this.matchHomeAccountId(entity, filter.homeAccountId)) {
296
- return false;
297
- }
298
- if (!!filter.environment &&
299
- !this.matchEnvironment(entity, filter.environment)) {
300
- return false;
301
- }
302
- if (!!filter.realm && !this.matchRealm(entity, filter.realm)) {
303
- return false;
304
- }
305
- if (!!filter.credentialType &&
306
- !this.matchCredentialType(entity, filter.credentialType)) {
307
- return false;
308
- }
309
- if (!!filter.familyId && !this.matchFamilyId(entity, filter.familyId)) {
310
- return false;
311
- }
312
- /*
313
- * idTokens do not have "target", target specific refreshTokens do exist for some types of authentication
314
- * Resource specific refresh tokens case will be added when the support is deemed necessary
315
- */
316
- if (!!filter.target && !this.matchTarget(entity, filter.target)) {
317
- return false;
318
- }
319
- // If request OR cached entity has requested Claims Hash, check if they match
320
- if (filter.requestedClaimsHash || entity.requestedClaimsHash) {
321
- // Don't match if either is undefined or they are different
322
- if (entity.requestedClaimsHash !== filter.requestedClaimsHash) {
323
- return false;
324
- }
325
- }
326
- // Access Token with Auth Scheme specific matching
327
- if (entity.credentialType ===
328
- CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME) {
329
- if (!!filter.tokenType &&
330
- !this.matchTokenType(entity, filter.tokenType)) {
331
- return false;
332
- }
333
- // KeyId (sshKid) in request must match cached SSH certificate keyId because SSH cert is bound to a specific key
334
- if (filter.tokenType === AuthenticationScheme.SSH) {
335
- if (filter.keyId && !this.matchKeyId(entity, filter.keyId)) {
336
- return false;
337
- }
338
- }
339
- }
340
- return true;
341
- }
342
- /**
343
- * retrieve appMetadata matching all provided filters; if no filter is set, get all appMetadata
344
- * @param filter
345
- */
346
- getAppMetadataFilteredBy(filter) {
347
- return this.getAppMetadataFilteredByInternal(filter.environment, filter.clientId);
348
- }
349
- /**
350
- * Support function to help match appMetadata
351
- * @param environment
352
- * @param clientId
353
- */
354
- getAppMetadataFilteredByInternal(environment, clientId) {
355
- const allCacheKeys = this.getKeys();
356
- const matchingAppMetadata = {};
357
- allCacheKeys.forEach((cacheKey) => {
358
- // don't parse any non-appMetadata type cache entities
359
- if (!this.isAppMetadata(cacheKey)) {
360
- return;
361
- }
362
- // Attempt retrieval
363
- const entity = this.getAppMetadata(cacheKey);
364
- if (!entity) {
365
- return;
366
- }
367
- if (!!environment && !this.matchEnvironment(entity, environment)) {
368
- return;
369
- }
370
- if (!!clientId && !this.matchClientId(entity, clientId)) {
371
- return;
372
- }
373
- matchingAppMetadata[cacheKey] = entity;
374
- });
375
- return matchingAppMetadata;
376
- }
377
- /**
378
- * retrieve authorityMetadata that contains a matching alias
379
- * @param filter
380
- */
381
- getAuthorityMetadataByAlias(host) {
382
- const allCacheKeys = this.getAuthorityMetadataKeys();
383
- let matchedEntity = null;
384
- allCacheKeys.forEach((cacheKey) => {
385
- // don't parse any non-authorityMetadata type cache entities
386
- if (!this.isAuthorityMetadata(cacheKey) ||
387
- cacheKey.indexOf(this.clientId) === -1) {
388
- return;
389
- }
390
- // Attempt retrieval
391
- const entity = this.getAuthorityMetadata(cacheKey);
392
- if (!entity) {
393
- return;
394
- }
395
- if (entity.aliases.indexOf(host) === -1) {
396
- return;
397
- }
398
- matchedEntity = entity;
399
- });
400
- return matchedEntity;
401
- }
402
- /**
403
- * Removes all accounts and related tokens from cache.
404
- */
405
- async removeAllAccounts() {
406
- const allAccountKeys = this.getAccountKeys();
407
- const removedAccounts = [];
408
- allAccountKeys.forEach((cacheKey) => {
409
- removedAccounts.push(this.removeAccount(cacheKey));
410
- });
411
- await Promise.all(removedAccounts);
412
- }
413
- /**
414
- * Removes the account and related tokens for a given account key
415
- * @param account
416
- */
417
- async removeAccount(accountKey) {
418
- const account = this.getAccount(accountKey);
419
- if (!account) {
420
- return;
421
- }
422
- await this.removeAccountContext(account);
423
- this.removeItem(accountKey);
424
- }
425
- /**
426
- * Removes credentials associated with the provided account
427
- * @param account
428
- */
429
- async removeAccountContext(account) {
430
- const allTokenKeys = this.getTokenKeys();
431
- const accountId = account.generateAccountId();
432
- const removedCredentials = [];
433
- allTokenKeys.idToken.forEach((key) => {
434
- if (key.indexOf(accountId) === 0) {
435
- this.removeIdToken(key);
436
- }
437
- });
438
- allTokenKeys.accessToken.forEach((key) => {
439
- if (key.indexOf(accountId) === 0) {
440
- removedCredentials.push(this.removeAccessToken(key));
441
- }
442
- });
443
- allTokenKeys.refreshToken.forEach((key) => {
444
- if (key.indexOf(accountId) === 0) {
445
- this.removeRefreshToken(key);
446
- }
447
- });
448
- await Promise.all(removedCredentials);
449
- }
450
- /**
451
- * returns a boolean if the given credential is removed
452
- * @param credential
453
- */
454
- async removeAccessToken(key) {
455
- const credential = this.getAccessTokenCredential(key);
456
- if (!credential) {
457
- return;
458
- }
459
- // Remove Token Binding Key from key store for PoP Tokens Credentials
460
- if (credential.credentialType.toLowerCase() ===
461
- CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME.toLowerCase()) {
462
- if (credential.tokenType === AuthenticationScheme.POP) {
463
- const accessTokenWithAuthSchemeEntity = credential;
464
- const kid = accessTokenWithAuthSchemeEntity.keyId;
465
- if (kid) {
466
- try {
467
- await this.cryptoImpl.removeTokenBindingKey(kid);
468
- }
469
- catch (error) {
470
- throw createClientAuthError(bindingKeyNotRemoved);
471
- }
472
- }
473
- }
474
- }
475
- return this.removeItem(key);
476
- }
477
- /**
478
- * Removes all app metadata objects from cache.
479
- */
480
- removeAppMetadata() {
481
- const allCacheKeys = this.getKeys();
482
- allCacheKeys.forEach((cacheKey) => {
483
- if (this.isAppMetadata(cacheKey)) {
484
- this.removeItem(cacheKey);
485
- }
486
- });
487
- return true;
488
- }
489
- /**
490
- * Retrieve the cached credentials into a cacherecord
491
- * @param account
492
- * @param clientId
493
- * @param scopes
494
- * @param environment
495
- * @param authScheme
496
- */
497
- readCacheRecord(account, request, environment) {
498
- const tokenKeys = this.getTokenKeys();
499
- const cachedAccount = this.readAccountFromCache(account);
500
- const cachedIdToken = this.getIdToken(account, tokenKeys);
501
- const cachedAccessToken = this.getAccessToken(account, request, tokenKeys);
502
- const cachedRefreshToken = this.getRefreshToken(account, false, tokenKeys);
503
- const cachedAppMetadata = this.readAppMetadataFromCache(environment);
504
- if (cachedAccount && cachedIdToken) {
505
- cachedAccount.idTokenClaims = extractTokenClaims(cachedIdToken.secret, this.cryptoImpl.base64Decode);
506
- }
507
- return {
508
- account: cachedAccount,
509
- idToken: cachedIdToken,
510
- accessToken: cachedAccessToken,
511
- refreshToken: cachedRefreshToken,
512
- appMetadata: cachedAppMetadata,
513
- };
514
- }
515
- /**
516
- * Retrieve AccountEntity from cache
517
- * @param account
518
- */
519
- readAccountFromCache(account) {
520
- const accountKey = AccountEntity.generateAccountCacheKey(account);
521
- return this.getAccount(accountKey);
522
- }
523
- /**
524
- * Retrieve IdTokenEntity from cache
525
- * @param clientId
526
- * @param account
527
- * @param inputRealm
528
- */
529
- getIdToken(account, tokenKeys) {
530
- this.commonLogger.trace("CacheManager - getIdToken called");
531
- const idTokenFilter = {
532
- homeAccountId: account.homeAccountId,
533
- environment: account.environment,
534
- credentialType: CredentialType.ID_TOKEN,
535
- clientId: this.clientId,
536
- realm: account.tenantId,
537
- };
538
- const idTokens = this.getIdTokensByFilter(idTokenFilter, tokenKeys);
539
- const numIdTokens = idTokens.length;
540
- if (numIdTokens < 1) {
541
- this.commonLogger.info("CacheManager:getIdToken - No token found");
542
- return null;
543
- }
544
- else if (numIdTokens > 1) {
545
- this.commonLogger.info("CacheManager:getIdToken - Multiple id tokens found, clearing them");
546
- idTokens.forEach((idToken) => {
547
- this.removeIdToken(generateCredentialKey(idToken));
548
- });
549
- return null;
550
- }
551
- this.commonLogger.info("CacheManager:getIdToken - Returning id token");
552
- return idTokens[0];
553
- }
554
- /**
555
- * Gets all idTokens matching the given filter
556
- * @param filter
557
- * @returns
558
- */
559
- getIdTokensByFilter(filter, tokenKeys) {
560
- const idTokenKeys = (tokenKeys && tokenKeys.idToken) || this.getTokenKeys().idToken;
561
- const idTokens = [];
562
- idTokenKeys.forEach((key) => {
563
- if (!this.idTokenKeyMatchesFilter(key, {
564
- clientId: this.clientId,
565
- ...filter,
566
- })) {
567
- return;
568
- }
569
- const idToken = this.getIdTokenCredential(key);
570
- if (idToken && this.credentialMatchesFilter(idToken, filter)) {
571
- idTokens.push(idToken);
572
- }
573
- });
574
- return idTokens;
575
- }
576
- /**
577
- * Validate the cache key against filter before retrieving and parsing cache value
578
- * @param key
579
- * @param filter
580
- * @returns
581
- */
582
- idTokenKeyMatchesFilter(inputKey, filter) {
583
- const key = inputKey.toLowerCase();
584
- if (filter.clientId &&
585
- key.indexOf(filter.clientId.toLowerCase()) === -1) {
586
- return false;
587
- }
588
- if (filter.homeAccountId &&
589
- key.indexOf(filter.homeAccountId.toLowerCase()) === -1) {
590
- return false;
591
- }
592
- return true;
593
- }
594
- /**
595
- * Removes idToken from the cache
596
- * @param key
597
- */
598
- removeIdToken(key) {
599
- this.removeItem(key);
600
- }
601
- /**
602
- * Removes refresh token from the cache
603
- * @param key
604
- */
605
- removeRefreshToken(key) {
606
- this.removeItem(key);
607
- }
608
- /**
609
- * Retrieve AccessTokenEntity from cache
610
- * @param clientId
611
- * @param account
612
- * @param scopes
613
- * @param authScheme
614
- */
615
- getAccessToken(account, request, tokenKeys) {
616
- this.commonLogger.trace("CacheManager - getAccessToken called");
617
- const scopes = ScopeSet.createSearchScopes(request.scopes);
618
- const authScheme = request.authenticationScheme || AuthenticationScheme.BEARER;
619
- /*
620
- * Distinguish between Bearer and PoP/SSH token cache types
621
- * Cast to lowercase to handle "bearer" from ADFS
622
- */
623
- const credentialType = authScheme &&
624
- authScheme.toLowerCase() !==
625
- AuthenticationScheme.BEARER.toLowerCase()
626
- ? CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME
627
- : CredentialType.ACCESS_TOKEN;
628
- const accessTokenFilter = {
629
- homeAccountId: account.homeAccountId,
630
- environment: account.environment,
631
- credentialType: credentialType,
632
- clientId: this.clientId,
633
- realm: account.tenantId,
634
- target: scopes,
635
- tokenType: authScheme,
636
- keyId: request.sshKid,
637
- requestedClaimsHash: request.requestedClaimsHash,
638
- };
639
- const accessTokenKeys = (tokenKeys && tokenKeys.accessToken) ||
640
- this.getTokenKeys().accessToken;
641
- const accessTokens = [];
642
- accessTokenKeys.forEach((key) => {
643
- // Validate key
644
- if (this.accessTokenKeyMatchesFilter(key, accessTokenFilter, true)) {
645
- const accessToken = this.getAccessTokenCredential(key);
646
- // Validate value
647
- if (accessToken &&
648
- this.credentialMatchesFilter(accessToken, accessTokenFilter)) {
649
- accessTokens.push(accessToken);
650
- }
651
- }
652
- });
653
- const numAccessTokens = accessTokens.length;
654
- if (numAccessTokens < 1) {
655
- this.commonLogger.info("CacheManager:getAccessToken - No token found");
656
- return null;
657
- }
658
- else if (numAccessTokens > 1) {
659
- this.commonLogger.info("CacheManager:getAccessToken - Multiple access tokens found, clearing them");
660
- accessTokens.forEach((accessToken) => {
661
- void this.removeAccessToken(generateCredentialKey(accessToken));
662
- });
663
- return null;
664
- }
665
- this.commonLogger.info("CacheManager:getAccessToken - Returning access token");
666
- return accessTokens[0];
667
- }
668
- /**
669
- * Validate the cache key against filter before retrieving and parsing cache value
670
- * @param key
671
- * @param filter
672
- * @param keyMustContainAllScopes
673
- * @returns
674
- */
675
- accessTokenKeyMatchesFilter(inputKey, filter, keyMustContainAllScopes) {
676
- const key = inputKey.toLowerCase();
677
- if (filter.clientId &&
678
- key.indexOf(filter.clientId.toLowerCase()) === -1) {
679
- return false;
680
- }
681
- if (filter.homeAccountId &&
682
- key.indexOf(filter.homeAccountId.toLowerCase()) === -1) {
683
- return false;
684
- }
685
- if (filter.realm && key.indexOf(filter.realm.toLowerCase()) === -1) {
686
- return false;
687
- }
688
- if (filter.requestedClaimsHash &&
689
- key.indexOf(filter.requestedClaimsHash.toLowerCase()) === -1) {
690
- return false;
691
- }
692
- if (filter.target) {
693
- const scopes = filter.target.asArray();
694
- for (let i = 0; i < scopes.length; i++) {
695
- if (keyMustContainAllScopes &&
696
- !key.includes(scopes[i].toLowerCase())) {
697
- // When performing a cache lookup a missing scope would be a cache miss
698
- return false;
699
- }
700
- else if (!keyMustContainAllScopes &&
701
- key.includes(scopes[i].toLowerCase())) {
702
- // When performing a cache write, any token with a subset of requested scopes should be replaced
703
- return true;
704
- }
705
- }
706
- }
707
- return true;
708
- }
709
- /**
710
- * Gets all access tokens matching the filter
711
- * @param filter
712
- * @returns
713
- */
714
- getAccessTokensByFilter(filter) {
715
- const tokenKeys = this.getTokenKeys();
716
- const accessTokens = [];
717
- tokenKeys.accessToken.forEach((key) => {
718
- if (!this.accessTokenKeyMatchesFilter(key, filter, true)) {
719
- return;
720
- }
721
- const accessToken = this.getAccessTokenCredential(key);
722
- if (accessToken &&
723
- this.credentialMatchesFilter(accessToken, filter)) {
724
- accessTokens.push(accessToken);
725
- }
726
- });
727
- return accessTokens;
728
- }
729
- /**
730
- * Helper to retrieve the appropriate refresh token from cache
731
- * @param clientId
732
- * @param account
733
- * @param familyRT
734
- */
735
- getRefreshToken(account, familyRT, tokenKeys) {
736
- this.commonLogger.trace("CacheManager - getRefreshToken called");
737
- const id = familyRT ? THE_FAMILY_ID : undefined;
738
- const refreshTokenFilter = {
739
- homeAccountId: account.homeAccountId,
740
- environment: account.environment,
741
- credentialType: CredentialType.REFRESH_TOKEN,
742
- clientId: this.clientId,
743
- familyId: id,
744
- };
745
- const refreshTokenKeys = (tokenKeys && tokenKeys.refreshToken) ||
746
- this.getTokenKeys().refreshToken;
747
- const refreshTokens = [];
748
- refreshTokenKeys.forEach((key) => {
749
- // Validate key
750
- if (this.refreshTokenKeyMatchesFilter(key, refreshTokenFilter)) {
751
- const refreshToken = this.getRefreshTokenCredential(key);
752
- // Validate value
753
- if (refreshToken &&
754
- this.credentialMatchesFilter(refreshToken, refreshTokenFilter)) {
755
- refreshTokens.push(refreshToken);
756
- }
757
- }
758
- });
759
- const numRefreshTokens = refreshTokens.length;
760
- if (numRefreshTokens < 1) {
761
- this.commonLogger.info("CacheManager:getRefreshToken - No refresh token found.");
762
- return null;
763
- }
764
- // address the else case after remove functions address environment aliases
765
- this.commonLogger.info("CacheManager:getRefreshToken - returning refresh token");
766
- return refreshTokens[0];
767
- }
768
- /**
769
- * Validate the cache key against filter before retrieving and parsing cache value
770
- * @param key
771
- * @param filter
772
- */
773
- refreshTokenKeyMatchesFilter(inputKey, filter) {
774
- const key = inputKey.toLowerCase();
775
- if (filter.familyId &&
776
- key.indexOf(filter.familyId.toLowerCase()) === -1) {
777
- return false;
778
- }
779
- // If familyId is used, clientId is not in the key
780
- if (!filter.familyId &&
781
- filter.clientId &&
782
- key.indexOf(filter.clientId.toLowerCase()) === -1) {
783
- return false;
784
- }
785
- if (filter.homeAccountId &&
786
- key.indexOf(filter.homeAccountId.toLowerCase()) === -1) {
787
- return false;
788
- }
789
- return true;
790
- }
791
- /**
792
- * Retrieve AppMetadataEntity from cache
793
- */
794
- readAppMetadataFromCache(environment) {
795
- const appMetadataFilter = {
796
- environment,
797
- clientId: this.clientId,
798
- };
799
- const appMetadata = this.getAppMetadataFilteredBy(appMetadataFilter);
800
- const appMetadataEntries = Object.keys(appMetadata).map((key) => appMetadata[key]);
801
- const numAppMetadata = appMetadataEntries.length;
802
- if (numAppMetadata < 1) {
803
- return null;
804
- }
805
- else if (numAppMetadata > 1) {
806
- throw createClientAuthError(multipleMatchingAppMetadata);
807
- }
808
- return appMetadataEntries[0];
809
- }
810
- /**
811
- * Return the family_id value associated with FOCI
812
- * @param environment
813
- * @param clientId
814
- */
815
- isAppMetadataFOCI(environment) {
816
- const appMetadata = this.readAppMetadataFromCache(environment);
817
- return !!(appMetadata && appMetadata.familyId === THE_FAMILY_ID);
818
- }
819
- /**
820
- * helper to match account ids
821
- * @param value
822
- * @param homeAccountId
823
- */
824
- matchHomeAccountId(entity, homeAccountId) {
825
- return !!(typeof entity.homeAccountId === "string" &&
826
- homeAccountId === entity.homeAccountId);
827
- }
828
- /**
829
- * helper to match account ids
830
- * @param entity
831
- * @param localAccountId
832
- * @returns
833
- */
834
- matchLocalAccountId(entity, localAccountId) {
835
- return !!(typeof entity.localAccountId === "string" &&
836
- localAccountId === entity.localAccountId);
837
- }
838
- /**
839
- * helper to match usernames
840
- * @param entity
841
- * @param username
842
- * @returns
843
- */
844
- matchUsername(entity, username) {
845
- return !!(typeof entity.username === "string" &&
846
- username.toLowerCase() === entity.username.toLowerCase());
847
- }
848
- /**
849
- * helper to match names
850
- * @param entity
851
- * @param name
852
- * @returns true if the downcased name properties are present and match in the filter and the entity
853
- */
854
- matchName(entity, name) {
855
- return !!(name.toLowerCase() === entity.name?.toLowerCase());
856
- }
857
- /**
858
- * helper to match assertion
859
- * @param value
860
- * @param oboAssertion
861
- */
862
- matchUserAssertionHash(entity, userAssertionHash) {
863
- return !!(entity.userAssertionHash &&
864
- userAssertionHash === entity.userAssertionHash);
865
- }
866
- /**
867
- * helper to match environment
868
- * @param value
869
- * @param environment
870
- */
871
- matchEnvironment(entity, environment) {
872
- // Check static authority options first for cases where authority metadata has not been resolved and cached yet
873
- if (this.staticAuthorityOptions) {
874
- const staticAliases = getAliasesFromStaticSources(this.staticAuthorityOptions, this.commonLogger);
875
- if (staticAliases.includes(environment) &&
876
- staticAliases.includes(entity.environment)) {
877
- return true;
878
- }
879
- }
880
- // Query metadata cache if no static authority configuration has aliases that match enviroment
881
- const cloudMetadata = this.getAuthorityMetadataByAlias(environment);
882
- if (cloudMetadata &&
883
- cloudMetadata.aliases.indexOf(entity.environment) > -1) {
884
- return true;
885
- }
886
- return false;
887
- }
888
- /**
889
- * helper to match credential type
890
- * @param entity
891
- * @param credentialType
892
- */
893
- matchCredentialType(entity, credentialType) {
894
- return (entity.credentialType &&
895
- credentialType.toLowerCase() === entity.credentialType.toLowerCase());
896
- }
897
- /**
898
- * helper to match client ids
899
- * @param entity
900
- * @param clientId
901
- */
902
- matchClientId(entity, clientId) {
903
- return !!(entity.clientId && clientId === entity.clientId);
904
- }
905
- /**
906
- * helper to match family ids
907
- * @param entity
908
- * @param familyId
909
- */
910
- matchFamilyId(entity, familyId) {
911
- return !!(entity.familyId && familyId === entity.familyId);
912
- }
913
- /**
914
- * helper to match realm
915
- * @param entity
916
- * @param realm
917
- */
918
- matchRealm(entity, realm) {
919
- return !!(entity.realm && realm === entity.realm);
920
- }
921
- /**
922
- * helper to match nativeAccountId
923
- * @param entity
924
- * @param nativeAccountId
925
- * @returns boolean indicating the match result
926
- */
927
- matchNativeAccountId(entity, nativeAccountId) {
928
- return !!(entity.nativeAccountId && nativeAccountId === entity.nativeAccountId);
929
- }
930
- /**
931
- * helper to match loginHint which can be either:
932
- * 1. login_hint ID token claim
933
- * 2. username in cached account object
934
- * 3. upn in ID token claims
935
- * @param entity
936
- * @param loginHint
937
- * @returns
938
- */
939
- matchLoginHint(idTokenClaims, loginHint) {
940
- if (idTokenClaims?.login_hint === loginHint) {
941
- return true;
942
- }
943
- if (idTokenClaims.preferred_username === loginHint) {
944
- return true;
945
- }
946
- if (idTokenClaims?.upn === loginHint) {
947
- return true;
948
- }
949
- return false;
950
- }
951
- /**
952
- * Helper to match sid
953
- * @param idTokenClaims
954
- * @param sid
955
- * @returns true if the sid claim is present and matches the filter
956
- */
957
- matchSid(idTokenClaims, sid) {
958
- return !!(idTokenClaims?.sid && idTokenClaims.sid === sid);
959
- }
960
- matchAuthorityType(entity, authorityType) {
961
- return !!(entity.authorityType &&
962
- authorityType.toLowerCase() === entity.authorityType.toLowerCase());
963
- }
964
- /**
965
- * Returns true if the target scopes are a subset of the current entity's scopes, false otherwise.
966
- * @param entity
967
- * @param target
968
- */
969
- matchTarget(entity, target) {
970
- const isNotAccessTokenCredential = entity.credentialType !== CredentialType.ACCESS_TOKEN &&
971
- entity.credentialType !==
972
- CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;
973
- if (isNotAccessTokenCredential || !entity.target) {
974
- return false;
975
- }
976
- const entityScopeSet = ScopeSet.fromString(entity.target);
977
- return entityScopeSet.containsScopeSet(target);
978
- }
979
- /**
980
- * Returns true if the credential's tokenType or Authentication Scheme matches the one in the request, false otherwise
981
- * @param entity
982
- * @param tokenType
983
- */
984
- matchTokenType(entity, tokenType) {
985
- return !!(entity.tokenType && entity.tokenType === tokenType);
986
- }
987
- /**
988
- * Returns true if the credential's keyId matches the one in the request, false otherwise
989
- * @param entity
990
- * @param tokenType
991
- */
992
- matchKeyId(entity, keyId) {
993
- return !!(entity.keyId && entity.keyId === keyId);
994
- }
995
- /**
996
- * returns if a given cache entity is of the type appmetadata
997
- * @param key
998
- */
999
- isAppMetadata(key) {
1000
- return key.indexOf(APP_METADATA) !== -1;
1001
- }
1002
- /**
1003
- * returns if a given cache entity is of the type authoritymetadata
1004
- * @param key
1005
- */
1006
- isAuthorityMetadata(key) {
1007
- return key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) !== -1;
1008
- }
1009
- /**
1010
- * returns cache key used for cloud instance metadata
1011
- */
1012
- generateAuthorityMetadataCacheKey(authority) {
1013
- return `${AUTHORITY_METADATA_CONSTANTS.CACHE_KEY}-${this.clientId}-${authority}`;
1014
- }
1015
- /**
1016
- * Helper to convert serialized data to object
1017
- * @param obj
1018
- * @param json
1019
- */
1020
- static toObject(obj, json) {
1021
- for (const propertyName in json) {
1022
- obj[propertyName] = json[propertyName];
1023
- }
1024
- return obj;
1025
- }
1026
- }
1027
- /** @internal */
1028
- class DefaultStorageClass extends CacheManager {
1029
- setAccount() {
1030
- throw createClientAuthError(methodNotImplemented);
1031
- }
1032
- getAccount() {
1033
- throw createClientAuthError(methodNotImplemented);
1034
- }
1035
- setIdTokenCredential() {
1036
- throw createClientAuthError(methodNotImplemented);
1037
- }
1038
- getIdTokenCredential() {
1039
- throw createClientAuthError(methodNotImplemented);
1040
- }
1041
- setAccessTokenCredential() {
1042
- throw createClientAuthError(methodNotImplemented);
1043
- }
1044
- getAccessTokenCredential() {
1045
- throw createClientAuthError(methodNotImplemented);
1046
- }
1047
- setRefreshTokenCredential() {
1048
- throw createClientAuthError(methodNotImplemented);
1049
- }
1050
- getRefreshTokenCredential() {
1051
- throw createClientAuthError(methodNotImplemented);
1052
- }
1053
- setAppMetadata() {
1054
- throw createClientAuthError(methodNotImplemented);
1055
- }
1056
- getAppMetadata() {
1057
- throw createClientAuthError(methodNotImplemented);
1058
- }
1059
- setServerTelemetry() {
1060
- throw createClientAuthError(methodNotImplemented);
1061
- }
1062
- getServerTelemetry() {
1063
- throw createClientAuthError(methodNotImplemented);
1064
- }
1065
- setAuthorityMetadata() {
1066
- throw createClientAuthError(methodNotImplemented);
1067
- }
1068
- getAuthorityMetadata() {
1069
- throw createClientAuthError(methodNotImplemented);
1070
- }
1071
- getAuthorityMetadataKeys() {
1072
- throw createClientAuthError(methodNotImplemented);
1073
- }
1074
- setThrottlingCache() {
1075
- throw createClientAuthError(methodNotImplemented);
1076
- }
1077
- getThrottlingCache() {
1078
- throw createClientAuthError(methodNotImplemented);
1079
- }
1080
- removeItem() {
1081
- throw createClientAuthError(methodNotImplemented);
1082
- }
1083
- containsKey() {
1084
- throw createClientAuthError(methodNotImplemented);
1085
- }
1086
- getKeys() {
1087
- throw createClientAuthError(methodNotImplemented);
1088
- }
1089
- getAccountKeys() {
1090
- throw createClientAuthError(methodNotImplemented);
1091
- }
1092
- getTokenKeys() {
1093
- throw createClientAuthError(methodNotImplemented);
1094
- }
1095
- async clear() {
1096
- throw createClientAuthError(methodNotImplemented);
1097
- }
1098
- updateCredentialCacheKey() {
1099
- throw createClientAuthError(methodNotImplemented);
1100
- }
13
+ /*
14
+ * Copyright (c) Microsoft Corporation. All rights reserved.
15
+ * Licensed under the MIT License.
16
+ */
17
+ /**
18
+ * Interface class which implement cache storage functions used by MSAL to perform validity checks, and store tokens.
19
+ * @internal
20
+ */
21
+ class CacheManager {
22
+ constructor(clientId, cryptoImpl, logger, staticAuthorityOptions) {
23
+ this.clientId = clientId;
24
+ this.cryptoImpl = cryptoImpl;
25
+ this.commonLogger = logger.clone(name, version);
26
+ this.staticAuthorityOptions = staticAuthorityOptions;
27
+ }
28
+ /**
29
+ * Returns all the accounts in the cache that match the optional filter. If no filter is provided, all accounts are returned.
30
+ * @param accountFilter - (Optional) filter to narrow down the accounts returned
31
+ * @returns Array of AccountInfo objects in cache
32
+ */
33
+ getAllAccounts(accountFilter) {
34
+ const validAccounts = [];
35
+ this.getAccountsFilteredBy(accountFilter || {}).forEach((accountEntity) => {
36
+ const accountInfo = this.getAccountInfoFromEntity(accountEntity, accountFilter);
37
+ if (accountInfo) {
38
+ validAccounts.push(accountInfo);
39
+ }
40
+ });
41
+ return validAccounts;
42
+ }
43
+ /**
44
+ * Gets accountInfo object based on provided filters
45
+ */
46
+ getAccountInfoFilteredBy(accountFilter) {
47
+ const allAccounts = this.getAllAccounts(accountFilter);
48
+ if (allAccounts.length > 1) {
49
+ // If one or more accounts are found, further filter to the first account that has an ID token
50
+ return allAccounts.filter((account) => {
51
+ return !!account.idTokenClaims;
52
+ })[0];
53
+ }
54
+ else if (allAccounts.length === 1) {
55
+ // If only one account is found, return it regardless of whether a matching ID token was found
56
+ return allAccounts[0];
57
+ }
58
+ else {
59
+ return null;
60
+ }
61
+ }
62
+ /**
63
+ * Returns a single matching
64
+ * @param accountFilter
65
+ * @returns
66
+ */
67
+ getBaseAccountInfo(accountFilter) {
68
+ const accountEntities = this.getAccountsFilteredBy(accountFilter);
69
+ if (accountEntities.length > 0) {
70
+ return accountEntities[0].getAccountInfo();
71
+ }
72
+ else {
73
+ return null;
74
+ }
75
+ }
76
+ getAccountInfoFromEntity(accountEntity, accountFilter) {
77
+ const accountInfo = accountEntity.getAccountInfo();
78
+ const idToken = this.getIdToken(accountInfo);
79
+ if (idToken) {
80
+ const idTokenClaims = extractTokenClaims(idToken.secret, this.cryptoImpl.base64Decode);
81
+ if (this.idTokenClaimsMatchAccountFilter(idTokenClaims, accountFilter)) {
82
+ accountInfo.idToken = idToken.secret;
83
+ accountInfo.idTokenClaims = idTokenClaims;
84
+ return accountInfo;
85
+ }
86
+ }
87
+ return accountInfo;
88
+ }
89
+ idTokenClaimsMatchAccountFilter(idTokenClaims, accountFilter) {
90
+ if (accountFilter) {
91
+ if (!!accountFilter.loginHint &&
92
+ !this.matchLoginHint(idTokenClaims, accountFilter.loginHint)) {
93
+ return false;
94
+ }
95
+ if (!!accountFilter.sid &&
96
+ !this.matchSid(idTokenClaims, accountFilter.sid)) {
97
+ return false;
98
+ }
99
+ }
100
+ return true;
101
+ }
102
+ /**
103
+ * saves a cache record
104
+ * @param cacheRecord
105
+ */
106
+ async saveCacheRecord(cacheRecord, storeInCache) {
107
+ if (!cacheRecord) {
108
+ throw createClientAuthError(invalidCacheRecord);
109
+ }
110
+ if (!!cacheRecord.account) {
111
+ this.setAccount(cacheRecord.account);
112
+ }
113
+ if (!!cacheRecord.idToken && storeInCache?.idToken !== false) {
114
+ this.setIdTokenCredential(cacheRecord.idToken);
115
+ }
116
+ if (!!cacheRecord.accessToken && storeInCache?.accessToken !== false) {
117
+ await this.saveAccessToken(cacheRecord.accessToken);
118
+ }
119
+ if (!!cacheRecord.refreshToken &&
120
+ storeInCache?.refreshToken !== false) {
121
+ this.setRefreshTokenCredential(cacheRecord.refreshToken);
122
+ }
123
+ if (!!cacheRecord.appMetadata) {
124
+ this.setAppMetadata(cacheRecord.appMetadata);
125
+ }
126
+ }
127
+ /**
128
+ * saves access token credential
129
+ * @param credential
130
+ */
131
+ async saveAccessToken(credential) {
132
+ const accessTokenFilter = {
133
+ clientId: credential.clientId,
134
+ credentialType: credential.credentialType,
135
+ environment: credential.environment,
136
+ homeAccountId: credential.homeAccountId,
137
+ realm: credential.realm,
138
+ tokenType: credential.tokenType,
139
+ requestedClaimsHash: credential.requestedClaimsHash,
140
+ };
141
+ const tokenKeys = this.getTokenKeys();
142
+ const currentScopes = ScopeSet.fromString(credential.target);
143
+ const removedAccessTokens = [];
144
+ tokenKeys.accessToken.forEach((key) => {
145
+ if (!this.accessTokenKeyMatchesFilter(key, accessTokenFilter, false)) {
146
+ return;
147
+ }
148
+ const tokenEntity = this.getAccessTokenCredential(key);
149
+ if (tokenEntity &&
150
+ this.credentialMatchesFilter(tokenEntity, accessTokenFilter)) {
151
+ const tokenScopeSet = ScopeSet.fromString(tokenEntity.target);
152
+ if (tokenScopeSet.intersectingScopeSets(currentScopes)) {
153
+ removedAccessTokens.push(this.removeAccessToken(key));
154
+ }
155
+ }
156
+ });
157
+ await Promise.all(removedAccessTokens);
158
+ this.setAccessTokenCredential(credential);
159
+ }
160
+ /**
161
+ * Retrieve accounts matching all provided filters; if no filter is set, get all accounts
162
+ * Not checking for casing as keys are all generated in lower case, remember to convert to lower case if object properties are compared
163
+ * @param accountFilter - An object containing Account properties to filter by
164
+ */
165
+ getAccountsFilteredBy(accountFilter) {
166
+ const allAccountKeys = this.getAccountKeys();
167
+ const matchingAccounts = [];
168
+ allAccountKeys.forEach((cacheKey) => {
169
+ if (!this.isAccountKey(cacheKey, accountFilter.homeAccountId, accountFilter.tenantId)) {
170
+ // Don't parse value if the key doesn't match the account filters
171
+ return;
172
+ }
173
+ const entity = this.getAccount(cacheKey);
174
+ if (!entity) {
175
+ return;
176
+ }
177
+ if (!!accountFilter.homeAccountId &&
178
+ !this.matchHomeAccountId(entity, accountFilter.homeAccountId)) {
179
+ return;
180
+ }
181
+ if (!!accountFilter.localAccountId &&
182
+ !this.matchLocalAccountId(entity, accountFilter.localAccountId)) {
183
+ return;
184
+ }
185
+ if (!!accountFilter.username &&
186
+ !this.matchUsername(entity, accountFilter.username)) {
187
+ return;
188
+ }
189
+ if (!!accountFilter.environment &&
190
+ !this.matchEnvironment(entity, accountFilter.environment)) {
191
+ return;
192
+ }
193
+ if (!!accountFilter.realm &&
194
+ !this.matchRealm(entity, accountFilter.realm)) {
195
+ return;
196
+ }
197
+ // tenantId is another name for realm
198
+ if (!!accountFilter.tenantId &&
199
+ !this.matchRealm(entity, accountFilter.tenantId)) {
200
+ return;
201
+ }
202
+ if (!!accountFilter.nativeAccountId &&
203
+ !this.matchNativeAccountId(entity, accountFilter.nativeAccountId)) {
204
+ return;
205
+ }
206
+ if (!!accountFilter.authorityType &&
207
+ !this.matchAuthorityType(entity, accountFilter.authorityType)) {
208
+ return;
209
+ }
210
+ if (!!accountFilter.name &&
211
+ !this.matchName(entity, accountFilter.name)) {
212
+ return;
213
+ }
214
+ matchingAccounts.push(entity);
215
+ });
216
+ return matchingAccounts;
217
+ }
218
+ /**
219
+ * Returns true if the given key matches our account key schema. Also matches homeAccountId and/or tenantId if provided
220
+ * @param key
221
+ * @param homeAccountId
222
+ * @param tenantId
223
+ * @returns
224
+ */
225
+ isAccountKey(key, homeAccountId, tenantId) {
226
+ if (key.split(Separators.CACHE_KEY_SEPARATOR).length < 3) {
227
+ // Account cache keys contain 3 items separated by '-' (each item may also contain '-')
228
+ return false;
229
+ }
230
+ if (homeAccountId &&
231
+ !key.toLowerCase().includes(homeAccountId.toLowerCase())) {
232
+ return false;
233
+ }
234
+ if (tenantId && !key.toLowerCase().includes(tenantId.toLowerCase())) {
235
+ return false;
236
+ }
237
+ // Do not check environment as aliasing can cause false negatives
238
+ return true;
239
+ }
240
+ /**
241
+ * Returns true if the given key matches our credential key schema.
242
+ * @param key
243
+ */
244
+ isCredentialKey(key) {
245
+ if (key.split(Separators.CACHE_KEY_SEPARATOR).length < 6) {
246
+ // Credential cache keys contain 6 items separated by '-' (each item may also contain '-')
247
+ return false;
248
+ }
249
+ const lowerCaseKey = key.toLowerCase();
250
+ // Credential keys must indicate what credential type they represent
251
+ if (lowerCaseKey.indexOf(CredentialType.ID_TOKEN.toLowerCase()) ===
252
+ -1 &&
253
+ lowerCaseKey.indexOf(CredentialType.ACCESS_TOKEN.toLowerCase()) ===
254
+ -1 &&
255
+ lowerCaseKey.indexOf(CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME.toLowerCase()) === -1 &&
256
+ lowerCaseKey.indexOf(CredentialType.REFRESH_TOKEN.toLowerCase()) ===
257
+ -1) {
258
+ return false;
259
+ }
260
+ if (lowerCaseKey.indexOf(CredentialType.REFRESH_TOKEN.toLowerCase()) >
261
+ -1) {
262
+ // Refresh tokens must contain the client id or family id
263
+ const clientIdValidation = `${CredentialType.REFRESH_TOKEN}${Separators.CACHE_KEY_SEPARATOR}${this.clientId}${Separators.CACHE_KEY_SEPARATOR}`;
264
+ const familyIdValidation = `${CredentialType.REFRESH_TOKEN}${Separators.CACHE_KEY_SEPARATOR}${THE_FAMILY_ID}${Separators.CACHE_KEY_SEPARATOR}`;
265
+ if (lowerCaseKey.indexOf(clientIdValidation.toLowerCase()) === -1 &&
266
+ lowerCaseKey.indexOf(familyIdValidation.toLowerCase()) === -1) {
267
+ return false;
268
+ }
269
+ }
270
+ else if (lowerCaseKey.indexOf(this.clientId.toLowerCase()) === -1) {
271
+ // Tokens must contain the clientId
272
+ return false;
273
+ }
274
+ return true;
275
+ }
276
+ /**
277
+ * Returns whether or not the given credential entity matches the filter
278
+ * @param entity
279
+ * @param filter
280
+ * @returns
281
+ */
282
+ credentialMatchesFilter(entity, filter) {
283
+ if (!!filter.clientId && !this.matchClientId(entity, filter.clientId)) {
284
+ return false;
285
+ }
286
+ if (!!filter.userAssertionHash &&
287
+ !this.matchUserAssertionHash(entity, filter.userAssertionHash)) {
288
+ return false;
289
+ }
290
+ /*
291
+ * homeAccountId can be undefined, and we want to filter out cached items that have a homeAccountId of ""
292
+ * because we don't want a client_credential request to return a cached token that has a homeAccountId
293
+ */
294
+ if (typeof filter.homeAccountId === "string" &&
295
+ !this.matchHomeAccountId(entity, filter.homeAccountId)) {
296
+ return false;
297
+ }
298
+ if (!!filter.environment &&
299
+ !this.matchEnvironment(entity, filter.environment)) {
300
+ return false;
301
+ }
302
+ if (!!filter.realm && !this.matchRealm(entity, filter.realm)) {
303
+ return false;
304
+ }
305
+ if (!!filter.credentialType &&
306
+ !this.matchCredentialType(entity, filter.credentialType)) {
307
+ return false;
308
+ }
309
+ if (!!filter.familyId && !this.matchFamilyId(entity, filter.familyId)) {
310
+ return false;
311
+ }
312
+ /*
313
+ * idTokens do not have "target", target specific refreshTokens do exist for some types of authentication
314
+ * Resource specific refresh tokens case will be added when the support is deemed necessary
315
+ */
316
+ if (!!filter.target && !this.matchTarget(entity, filter.target)) {
317
+ return false;
318
+ }
319
+ // If request OR cached entity has requested Claims Hash, check if they match
320
+ if (filter.requestedClaimsHash || entity.requestedClaimsHash) {
321
+ // Don't match if either is undefined or they are different
322
+ if (entity.requestedClaimsHash !== filter.requestedClaimsHash) {
323
+ return false;
324
+ }
325
+ }
326
+ // Access Token with Auth Scheme specific matching
327
+ if (entity.credentialType ===
328
+ CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME) {
329
+ if (!!filter.tokenType &&
330
+ !this.matchTokenType(entity, filter.tokenType)) {
331
+ return false;
332
+ }
333
+ // KeyId (sshKid) in request must match cached SSH certificate keyId because SSH cert is bound to a specific key
334
+ if (filter.tokenType === AuthenticationScheme.SSH) {
335
+ if (filter.keyId && !this.matchKeyId(entity, filter.keyId)) {
336
+ return false;
337
+ }
338
+ }
339
+ }
340
+ return true;
341
+ }
342
+ /**
343
+ * retrieve appMetadata matching all provided filters; if no filter is set, get all appMetadata
344
+ * @param filter
345
+ */
346
+ getAppMetadataFilteredBy(filter) {
347
+ return this.getAppMetadataFilteredByInternal(filter.environment, filter.clientId);
348
+ }
349
+ /**
350
+ * Support function to help match appMetadata
351
+ * @param environment
352
+ * @param clientId
353
+ */
354
+ getAppMetadataFilteredByInternal(environment, clientId) {
355
+ const allCacheKeys = this.getKeys();
356
+ const matchingAppMetadata = {};
357
+ allCacheKeys.forEach((cacheKey) => {
358
+ // don't parse any non-appMetadata type cache entities
359
+ if (!this.isAppMetadata(cacheKey)) {
360
+ return;
361
+ }
362
+ // Attempt retrieval
363
+ const entity = this.getAppMetadata(cacheKey);
364
+ if (!entity) {
365
+ return;
366
+ }
367
+ if (!!environment && !this.matchEnvironment(entity, environment)) {
368
+ return;
369
+ }
370
+ if (!!clientId && !this.matchClientId(entity, clientId)) {
371
+ return;
372
+ }
373
+ matchingAppMetadata[cacheKey] = entity;
374
+ });
375
+ return matchingAppMetadata;
376
+ }
377
+ /**
378
+ * retrieve authorityMetadata that contains a matching alias
379
+ * @param filter
380
+ */
381
+ getAuthorityMetadataByAlias(host) {
382
+ const allCacheKeys = this.getAuthorityMetadataKeys();
383
+ let matchedEntity = null;
384
+ allCacheKeys.forEach((cacheKey) => {
385
+ // don't parse any non-authorityMetadata type cache entities
386
+ if (!this.isAuthorityMetadata(cacheKey) ||
387
+ cacheKey.indexOf(this.clientId) === -1) {
388
+ return;
389
+ }
390
+ // Attempt retrieval
391
+ const entity = this.getAuthorityMetadata(cacheKey);
392
+ if (!entity) {
393
+ return;
394
+ }
395
+ if (entity.aliases.indexOf(host) === -1) {
396
+ return;
397
+ }
398
+ matchedEntity = entity;
399
+ });
400
+ return matchedEntity;
401
+ }
402
+ /**
403
+ * Removes all accounts and related tokens from cache.
404
+ */
405
+ async removeAllAccounts() {
406
+ const allAccountKeys = this.getAccountKeys();
407
+ const removedAccounts = [];
408
+ allAccountKeys.forEach((cacheKey) => {
409
+ removedAccounts.push(this.removeAccount(cacheKey));
410
+ });
411
+ await Promise.all(removedAccounts);
412
+ }
413
+ /**
414
+ * Removes the account and related tokens for a given account key
415
+ * @param account
416
+ */
417
+ async removeAccount(accountKey) {
418
+ const account = this.getAccount(accountKey);
419
+ if (!account) {
420
+ return;
421
+ }
422
+ await this.removeAccountContext(account);
423
+ this.removeItem(accountKey);
424
+ }
425
+ /**
426
+ * Removes credentials associated with the provided account
427
+ * @param account
428
+ */
429
+ async removeAccountContext(account) {
430
+ const allTokenKeys = this.getTokenKeys();
431
+ const accountId = account.generateAccountId();
432
+ const removedCredentials = [];
433
+ allTokenKeys.idToken.forEach((key) => {
434
+ if (key.indexOf(accountId) === 0) {
435
+ this.removeIdToken(key);
436
+ }
437
+ });
438
+ allTokenKeys.accessToken.forEach((key) => {
439
+ if (key.indexOf(accountId) === 0) {
440
+ removedCredentials.push(this.removeAccessToken(key));
441
+ }
442
+ });
443
+ allTokenKeys.refreshToken.forEach((key) => {
444
+ if (key.indexOf(accountId) === 0) {
445
+ this.removeRefreshToken(key);
446
+ }
447
+ });
448
+ await Promise.all(removedCredentials);
449
+ }
450
+ /**
451
+ * returns a boolean if the given credential is removed
452
+ * @param credential
453
+ */
454
+ async removeAccessToken(key) {
455
+ const credential = this.getAccessTokenCredential(key);
456
+ if (!credential) {
457
+ return;
458
+ }
459
+ // Remove Token Binding Key from key store for PoP Tokens Credentials
460
+ if (credential.credentialType.toLowerCase() ===
461
+ CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME.toLowerCase()) {
462
+ if (credential.tokenType === AuthenticationScheme.POP) {
463
+ const accessTokenWithAuthSchemeEntity = credential;
464
+ const kid = accessTokenWithAuthSchemeEntity.keyId;
465
+ if (kid) {
466
+ try {
467
+ await this.cryptoImpl.removeTokenBindingKey(kid);
468
+ }
469
+ catch (error) {
470
+ throw createClientAuthError(bindingKeyNotRemoved);
471
+ }
472
+ }
473
+ }
474
+ }
475
+ return this.removeItem(key);
476
+ }
477
+ /**
478
+ * Removes all app metadata objects from cache.
479
+ */
480
+ removeAppMetadata() {
481
+ const allCacheKeys = this.getKeys();
482
+ allCacheKeys.forEach((cacheKey) => {
483
+ if (this.isAppMetadata(cacheKey)) {
484
+ this.removeItem(cacheKey);
485
+ }
486
+ });
487
+ return true;
488
+ }
489
+ /**
490
+ * Retrieve the cached credentials into a cacherecord
491
+ * @param account {AccountInfo}
492
+ * @param request {BaseAuthRequest}
493
+ * @param environment {string}
494
+ * @param performanceClient {?IPerformanceClient}
495
+ * @param correlationId {?string}
496
+ */
497
+ readCacheRecord(account, request, environment, performanceClient, correlationId) {
498
+ const tokenKeys = this.getTokenKeys();
499
+ const cachedAccount = this.readAccountFromCache(account);
500
+ const cachedIdToken = this.getIdToken(account, tokenKeys, performanceClient, correlationId);
501
+ const cachedAccessToken = this.getAccessToken(account, request, tokenKeys, performanceClient, correlationId);
502
+ const cachedRefreshToken = this.getRefreshToken(account, false, tokenKeys, performanceClient, correlationId);
503
+ const cachedAppMetadata = this.readAppMetadataFromCache(environment);
504
+ if (cachedAccount && cachedIdToken) {
505
+ cachedAccount.idTokenClaims = extractTokenClaims(cachedIdToken.secret, this.cryptoImpl.base64Decode);
506
+ }
507
+ return {
508
+ account: cachedAccount,
509
+ idToken: cachedIdToken,
510
+ accessToken: cachedAccessToken,
511
+ refreshToken: cachedRefreshToken,
512
+ appMetadata: cachedAppMetadata,
513
+ };
514
+ }
515
+ /**
516
+ * Retrieve AccountEntity from cache
517
+ * @param account
518
+ */
519
+ readAccountFromCache(account) {
520
+ const accountKey = AccountEntity.generateAccountCacheKey(account);
521
+ return this.getAccount(accountKey);
522
+ }
523
+ /**
524
+ * Retrieve IdTokenEntity from cache
525
+ * @param account {AccountInfo}
526
+ * @param tokenKeys {?TokenKeys}
527
+ * @param performanceClient {?IPerformanceClient}
528
+ * @param correlationId {?string}
529
+ */
530
+ getIdToken(account, tokenKeys, performanceClient, correlationId) {
531
+ this.commonLogger.trace("CacheManager - getIdToken called");
532
+ const idTokenFilter = {
533
+ homeAccountId: account.homeAccountId,
534
+ environment: account.environment,
535
+ credentialType: CredentialType.ID_TOKEN,
536
+ clientId: this.clientId,
537
+ realm: account.tenantId,
538
+ };
539
+ const idTokens = this.getIdTokensByFilter(idTokenFilter, tokenKeys);
540
+ const numIdTokens = idTokens.length;
541
+ if (numIdTokens < 1) {
542
+ this.commonLogger.info("CacheManager:getIdToken - No token found");
543
+ return null;
544
+ }
545
+ else if (numIdTokens > 1) {
546
+ this.commonLogger.info("CacheManager:getIdToken - Multiple id tokens found, clearing them");
547
+ idTokens.forEach((idToken) => {
548
+ this.removeIdToken(generateCredentialKey(idToken));
549
+ });
550
+ if (performanceClient && correlationId) {
551
+ performanceClient.addFields({ multiMatchedID: idTokens.length }, correlationId);
552
+ }
553
+ return null;
554
+ }
555
+ this.commonLogger.info("CacheManager:getIdToken - Returning id token");
556
+ return idTokens[0];
557
+ }
558
+ /**
559
+ * Gets all idTokens matching the given filter
560
+ * @param filter
561
+ * @returns
562
+ */
563
+ getIdTokensByFilter(filter, tokenKeys) {
564
+ const idTokenKeys = (tokenKeys && tokenKeys.idToken) || this.getTokenKeys().idToken;
565
+ const idTokens = [];
566
+ idTokenKeys.forEach((key) => {
567
+ if (!this.idTokenKeyMatchesFilter(key, {
568
+ clientId: this.clientId,
569
+ ...filter,
570
+ })) {
571
+ return;
572
+ }
573
+ const idToken = this.getIdTokenCredential(key);
574
+ if (idToken && this.credentialMatchesFilter(idToken, filter)) {
575
+ idTokens.push(idToken);
576
+ }
577
+ });
578
+ return idTokens;
579
+ }
580
+ /**
581
+ * Validate the cache key against filter before retrieving and parsing cache value
582
+ * @param key
583
+ * @param filter
584
+ * @returns
585
+ */
586
+ idTokenKeyMatchesFilter(inputKey, filter) {
587
+ const key = inputKey.toLowerCase();
588
+ if (filter.clientId &&
589
+ key.indexOf(filter.clientId.toLowerCase()) === -1) {
590
+ return false;
591
+ }
592
+ if (filter.homeAccountId &&
593
+ key.indexOf(filter.homeAccountId.toLowerCase()) === -1) {
594
+ return false;
595
+ }
596
+ return true;
597
+ }
598
+ /**
599
+ * Removes idToken from the cache
600
+ * @param key
601
+ */
602
+ removeIdToken(key) {
603
+ this.removeItem(key);
604
+ }
605
+ /**
606
+ * Removes refresh token from the cache
607
+ * @param key
608
+ */
609
+ removeRefreshToken(key) {
610
+ this.removeItem(key);
611
+ }
612
+ /**
613
+ * Retrieve AccessTokenEntity from cache
614
+ * @param account {AccountInfo}
615
+ * @param request {BaseAuthRequest}
616
+ * @param tokenKeys {?TokenKeys}
617
+ * @param performanceClient {?IPerformanceClient}
618
+ * @param correlationId {?string}
619
+ */
620
+ getAccessToken(account, request, tokenKeys, performanceClient, correlationId) {
621
+ this.commonLogger.trace("CacheManager - getAccessToken called");
622
+ const scopes = ScopeSet.createSearchScopes(request.scopes);
623
+ const authScheme = request.authenticationScheme || AuthenticationScheme.BEARER;
624
+ /*
625
+ * Distinguish between Bearer and PoP/SSH token cache types
626
+ * Cast to lowercase to handle "bearer" from ADFS
627
+ */
628
+ const credentialType = authScheme &&
629
+ authScheme.toLowerCase() !==
630
+ AuthenticationScheme.BEARER.toLowerCase()
631
+ ? CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME
632
+ : CredentialType.ACCESS_TOKEN;
633
+ const accessTokenFilter = {
634
+ homeAccountId: account.homeAccountId,
635
+ environment: account.environment,
636
+ credentialType: credentialType,
637
+ clientId: this.clientId,
638
+ realm: account.tenantId,
639
+ target: scopes,
640
+ tokenType: authScheme,
641
+ keyId: request.sshKid,
642
+ requestedClaimsHash: request.requestedClaimsHash,
643
+ };
644
+ const accessTokenKeys = (tokenKeys && tokenKeys.accessToken) ||
645
+ this.getTokenKeys().accessToken;
646
+ const accessTokens = [];
647
+ accessTokenKeys.forEach((key) => {
648
+ // Validate key
649
+ if (this.accessTokenKeyMatchesFilter(key, accessTokenFilter, true)) {
650
+ const accessToken = this.getAccessTokenCredential(key);
651
+ // Validate value
652
+ if (accessToken &&
653
+ this.credentialMatchesFilter(accessToken, accessTokenFilter)) {
654
+ accessTokens.push(accessToken);
655
+ }
656
+ }
657
+ });
658
+ const numAccessTokens = accessTokens.length;
659
+ if (numAccessTokens < 1) {
660
+ this.commonLogger.info("CacheManager:getAccessToken - No token found");
661
+ return null;
662
+ }
663
+ else if (numAccessTokens > 1) {
664
+ this.commonLogger.info("CacheManager:getAccessToken - Multiple access tokens found, clearing them");
665
+ accessTokens.forEach((accessToken) => {
666
+ void this.removeAccessToken(generateCredentialKey(accessToken));
667
+ });
668
+ if (performanceClient && correlationId) {
669
+ performanceClient.addFields({ multiMatchedAT: accessTokens.length }, correlationId);
670
+ }
671
+ return null;
672
+ }
673
+ this.commonLogger.info("CacheManager:getAccessToken - Returning access token");
674
+ return accessTokens[0];
675
+ }
676
+ /**
677
+ * Validate the cache key against filter before retrieving and parsing cache value
678
+ * @param key
679
+ * @param filter
680
+ * @param keyMustContainAllScopes
681
+ * @returns
682
+ */
683
+ accessTokenKeyMatchesFilter(inputKey, filter, keyMustContainAllScopes) {
684
+ const key = inputKey.toLowerCase();
685
+ if (filter.clientId &&
686
+ key.indexOf(filter.clientId.toLowerCase()) === -1) {
687
+ return false;
688
+ }
689
+ if (filter.homeAccountId &&
690
+ key.indexOf(filter.homeAccountId.toLowerCase()) === -1) {
691
+ return false;
692
+ }
693
+ if (filter.realm && key.indexOf(filter.realm.toLowerCase()) === -1) {
694
+ return false;
695
+ }
696
+ if (filter.requestedClaimsHash &&
697
+ key.indexOf(filter.requestedClaimsHash.toLowerCase()) === -1) {
698
+ return false;
699
+ }
700
+ if (filter.target) {
701
+ const scopes = filter.target.asArray();
702
+ for (let i = 0; i < scopes.length; i++) {
703
+ if (keyMustContainAllScopes &&
704
+ !key.includes(scopes[i].toLowerCase())) {
705
+ // When performing a cache lookup a missing scope would be a cache miss
706
+ return false;
707
+ }
708
+ else if (!keyMustContainAllScopes &&
709
+ key.includes(scopes[i].toLowerCase())) {
710
+ // When performing a cache write, any token with a subset of requested scopes should be replaced
711
+ return true;
712
+ }
713
+ }
714
+ }
715
+ return true;
716
+ }
717
+ /**
718
+ * Gets all access tokens matching the filter
719
+ * @param filter
720
+ * @returns
721
+ */
722
+ getAccessTokensByFilter(filter) {
723
+ const tokenKeys = this.getTokenKeys();
724
+ const accessTokens = [];
725
+ tokenKeys.accessToken.forEach((key) => {
726
+ if (!this.accessTokenKeyMatchesFilter(key, filter, true)) {
727
+ return;
728
+ }
729
+ const accessToken = this.getAccessTokenCredential(key);
730
+ if (accessToken &&
731
+ this.credentialMatchesFilter(accessToken, filter)) {
732
+ accessTokens.push(accessToken);
733
+ }
734
+ });
735
+ return accessTokens;
736
+ }
737
+ /**
738
+ * Helper to retrieve the appropriate refresh token from cache
739
+ * @param account {AccountInfo}
740
+ * @param familyRT {boolean}
741
+ * @param tokenKeys {?TokenKeys}
742
+ * @param performanceClient {?IPerformanceClient}
743
+ * @param correlationId {?string}
744
+ */
745
+ getRefreshToken(account, familyRT, tokenKeys, performanceClient, correlationId) {
746
+ this.commonLogger.trace("CacheManager - getRefreshToken called");
747
+ const id = familyRT ? THE_FAMILY_ID : undefined;
748
+ const refreshTokenFilter = {
749
+ homeAccountId: account.homeAccountId,
750
+ environment: account.environment,
751
+ credentialType: CredentialType.REFRESH_TOKEN,
752
+ clientId: this.clientId,
753
+ familyId: id,
754
+ };
755
+ const refreshTokenKeys = (tokenKeys && tokenKeys.refreshToken) ||
756
+ this.getTokenKeys().refreshToken;
757
+ const refreshTokens = [];
758
+ refreshTokenKeys.forEach((key) => {
759
+ // Validate key
760
+ if (this.refreshTokenKeyMatchesFilter(key, refreshTokenFilter)) {
761
+ const refreshToken = this.getRefreshTokenCredential(key);
762
+ // Validate value
763
+ if (refreshToken &&
764
+ this.credentialMatchesFilter(refreshToken, refreshTokenFilter)) {
765
+ refreshTokens.push(refreshToken);
766
+ }
767
+ }
768
+ });
769
+ const numRefreshTokens = refreshTokens.length;
770
+ if (numRefreshTokens < 1) {
771
+ this.commonLogger.info("CacheManager:getRefreshToken - No refresh token found.");
772
+ return null;
773
+ }
774
+ // address the else case after remove functions address environment aliases
775
+ if (numRefreshTokens > 1 && performanceClient && correlationId) {
776
+ performanceClient.addFields({ multiMatchedRT: numRefreshTokens }, correlationId);
777
+ }
778
+ this.commonLogger.info("CacheManager:getRefreshToken - returning refresh token");
779
+ return refreshTokens[0];
780
+ }
781
+ /**
782
+ * Validate the cache key against filter before retrieving and parsing cache value
783
+ * @param key
784
+ * @param filter
785
+ */
786
+ refreshTokenKeyMatchesFilter(inputKey, filter) {
787
+ const key = inputKey.toLowerCase();
788
+ if (filter.familyId &&
789
+ key.indexOf(filter.familyId.toLowerCase()) === -1) {
790
+ return false;
791
+ }
792
+ // If familyId is used, clientId is not in the key
793
+ if (!filter.familyId &&
794
+ filter.clientId &&
795
+ key.indexOf(filter.clientId.toLowerCase()) === -1) {
796
+ return false;
797
+ }
798
+ if (filter.homeAccountId &&
799
+ key.indexOf(filter.homeAccountId.toLowerCase()) === -1) {
800
+ return false;
801
+ }
802
+ return true;
803
+ }
804
+ /**
805
+ * Retrieve AppMetadataEntity from cache
806
+ */
807
+ readAppMetadataFromCache(environment) {
808
+ const appMetadataFilter = {
809
+ environment,
810
+ clientId: this.clientId,
811
+ };
812
+ const appMetadata = this.getAppMetadataFilteredBy(appMetadataFilter);
813
+ const appMetadataEntries = Object.keys(appMetadata).map((key) => appMetadata[key]);
814
+ const numAppMetadata = appMetadataEntries.length;
815
+ if (numAppMetadata < 1) {
816
+ return null;
817
+ }
818
+ else if (numAppMetadata > 1) {
819
+ throw createClientAuthError(multipleMatchingAppMetadata);
820
+ }
821
+ return appMetadataEntries[0];
822
+ }
823
+ /**
824
+ * Return the family_id value associated with FOCI
825
+ * @param environment
826
+ * @param clientId
827
+ */
828
+ isAppMetadataFOCI(environment) {
829
+ const appMetadata = this.readAppMetadataFromCache(environment);
830
+ return !!(appMetadata && appMetadata.familyId === THE_FAMILY_ID);
831
+ }
832
+ /**
833
+ * helper to match account ids
834
+ * @param value
835
+ * @param homeAccountId
836
+ */
837
+ matchHomeAccountId(entity, homeAccountId) {
838
+ return !!(typeof entity.homeAccountId === "string" &&
839
+ homeAccountId === entity.homeAccountId);
840
+ }
841
+ /**
842
+ * helper to match account ids
843
+ * @param entity
844
+ * @param localAccountId
845
+ * @returns
846
+ */
847
+ matchLocalAccountId(entity, localAccountId) {
848
+ return !!(typeof entity.localAccountId === "string" &&
849
+ localAccountId === entity.localAccountId);
850
+ }
851
+ /**
852
+ * helper to match usernames
853
+ * @param entity
854
+ * @param username
855
+ * @returns
856
+ */
857
+ matchUsername(entity, username) {
858
+ return !!(typeof entity.username === "string" &&
859
+ username.toLowerCase() === entity.username.toLowerCase());
860
+ }
861
+ /**
862
+ * helper to match names
863
+ * @param entity
864
+ * @param name
865
+ * @returns true if the downcased name properties are present and match in the filter and the entity
866
+ */
867
+ matchName(entity, name) {
868
+ return !!(name.toLowerCase() === entity.name?.toLowerCase());
869
+ }
870
+ /**
871
+ * helper to match assertion
872
+ * @param value
873
+ * @param oboAssertion
874
+ */
875
+ matchUserAssertionHash(entity, userAssertionHash) {
876
+ return !!(entity.userAssertionHash &&
877
+ userAssertionHash === entity.userAssertionHash);
878
+ }
879
+ /**
880
+ * helper to match environment
881
+ * @param value
882
+ * @param environment
883
+ */
884
+ matchEnvironment(entity, environment) {
885
+ // Check static authority options first for cases where authority metadata has not been resolved and cached yet
886
+ if (this.staticAuthorityOptions) {
887
+ const staticAliases = getAliasesFromStaticSources(this.staticAuthorityOptions, this.commonLogger);
888
+ if (staticAliases.includes(environment) &&
889
+ staticAliases.includes(entity.environment)) {
890
+ return true;
891
+ }
892
+ }
893
+ // Query metadata cache if no static authority configuration has aliases that match enviroment
894
+ const cloudMetadata = this.getAuthorityMetadataByAlias(environment);
895
+ if (cloudMetadata &&
896
+ cloudMetadata.aliases.indexOf(entity.environment) > -1) {
897
+ return true;
898
+ }
899
+ return false;
900
+ }
901
+ /**
902
+ * helper to match credential type
903
+ * @param entity
904
+ * @param credentialType
905
+ */
906
+ matchCredentialType(entity, credentialType) {
907
+ return (entity.credentialType &&
908
+ credentialType.toLowerCase() === entity.credentialType.toLowerCase());
909
+ }
910
+ /**
911
+ * helper to match client ids
912
+ * @param entity
913
+ * @param clientId
914
+ */
915
+ matchClientId(entity, clientId) {
916
+ return !!(entity.clientId && clientId === entity.clientId);
917
+ }
918
+ /**
919
+ * helper to match family ids
920
+ * @param entity
921
+ * @param familyId
922
+ */
923
+ matchFamilyId(entity, familyId) {
924
+ return !!(entity.familyId && familyId === entity.familyId);
925
+ }
926
+ /**
927
+ * helper to match realm
928
+ * @param entity
929
+ * @param realm
930
+ */
931
+ matchRealm(entity, realm) {
932
+ return !!(entity.realm && realm === entity.realm);
933
+ }
934
+ /**
935
+ * helper to match nativeAccountId
936
+ * @param entity
937
+ * @param nativeAccountId
938
+ * @returns boolean indicating the match result
939
+ */
940
+ matchNativeAccountId(entity, nativeAccountId) {
941
+ return !!(entity.nativeAccountId && nativeAccountId === entity.nativeAccountId);
942
+ }
943
+ /**
944
+ * helper to match loginHint which can be either:
945
+ * 1. login_hint ID token claim
946
+ * 2. username in cached account object
947
+ * 3. upn in ID token claims
948
+ * @param entity
949
+ * @param loginHint
950
+ * @returns
951
+ */
952
+ matchLoginHint(idTokenClaims, loginHint) {
953
+ if (idTokenClaims?.login_hint === loginHint) {
954
+ return true;
955
+ }
956
+ if (idTokenClaims.preferred_username === loginHint) {
957
+ return true;
958
+ }
959
+ if (idTokenClaims?.upn === loginHint) {
960
+ return true;
961
+ }
962
+ return false;
963
+ }
964
+ /**
965
+ * Helper to match sid
966
+ * @param idTokenClaims
967
+ * @param sid
968
+ * @returns true if the sid claim is present and matches the filter
969
+ */
970
+ matchSid(idTokenClaims, sid) {
971
+ return !!(idTokenClaims?.sid && idTokenClaims.sid === sid);
972
+ }
973
+ matchAuthorityType(entity, authorityType) {
974
+ return !!(entity.authorityType &&
975
+ authorityType.toLowerCase() === entity.authorityType.toLowerCase());
976
+ }
977
+ /**
978
+ * Returns true if the target scopes are a subset of the current entity's scopes, false otherwise.
979
+ * @param entity
980
+ * @param target
981
+ */
982
+ matchTarget(entity, target) {
983
+ const isNotAccessTokenCredential = entity.credentialType !== CredentialType.ACCESS_TOKEN &&
984
+ entity.credentialType !==
985
+ CredentialType.ACCESS_TOKEN_WITH_AUTH_SCHEME;
986
+ if (isNotAccessTokenCredential || !entity.target) {
987
+ return false;
988
+ }
989
+ const entityScopeSet = ScopeSet.fromString(entity.target);
990
+ return entityScopeSet.containsScopeSet(target);
991
+ }
992
+ /**
993
+ * Returns true if the credential's tokenType or Authentication Scheme matches the one in the request, false otherwise
994
+ * @param entity
995
+ * @param tokenType
996
+ */
997
+ matchTokenType(entity, tokenType) {
998
+ return !!(entity.tokenType && entity.tokenType === tokenType);
999
+ }
1000
+ /**
1001
+ * Returns true if the credential's keyId matches the one in the request, false otherwise
1002
+ * @param entity
1003
+ * @param tokenType
1004
+ */
1005
+ matchKeyId(entity, keyId) {
1006
+ return !!(entity.keyId && entity.keyId === keyId);
1007
+ }
1008
+ /**
1009
+ * returns if a given cache entity is of the type appmetadata
1010
+ * @param key
1011
+ */
1012
+ isAppMetadata(key) {
1013
+ return key.indexOf(APP_METADATA) !== -1;
1014
+ }
1015
+ /**
1016
+ * returns if a given cache entity is of the type authoritymetadata
1017
+ * @param key
1018
+ */
1019
+ isAuthorityMetadata(key) {
1020
+ return key.indexOf(AUTHORITY_METADATA_CONSTANTS.CACHE_KEY) !== -1;
1021
+ }
1022
+ /**
1023
+ * returns cache key used for cloud instance metadata
1024
+ */
1025
+ generateAuthorityMetadataCacheKey(authority) {
1026
+ return `${AUTHORITY_METADATA_CONSTANTS.CACHE_KEY}-${this.clientId}-${authority}`;
1027
+ }
1028
+ /**
1029
+ * Helper to convert serialized data to object
1030
+ * @param obj
1031
+ * @param json
1032
+ */
1033
+ static toObject(obj, json) {
1034
+ for (const propertyName in json) {
1035
+ obj[propertyName] = json[propertyName];
1036
+ }
1037
+ return obj;
1038
+ }
1039
+ }
1040
+ /** @internal */
1041
+ class DefaultStorageClass extends CacheManager {
1042
+ setAccount() {
1043
+ throw createClientAuthError(methodNotImplemented);
1044
+ }
1045
+ getAccount() {
1046
+ throw createClientAuthError(methodNotImplemented);
1047
+ }
1048
+ setIdTokenCredential() {
1049
+ throw createClientAuthError(methodNotImplemented);
1050
+ }
1051
+ getIdTokenCredential() {
1052
+ throw createClientAuthError(methodNotImplemented);
1053
+ }
1054
+ setAccessTokenCredential() {
1055
+ throw createClientAuthError(methodNotImplemented);
1056
+ }
1057
+ getAccessTokenCredential() {
1058
+ throw createClientAuthError(methodNotImplemented);
1059
+ }
1060
+ setRefreshTokenCredential() {
1061
+ throw createClientAuthError(methodNotImplemented);
1062
+ }
1063
+ getRefreshTokenCredential() {
1064
+ throw createClientAuthError(methodNotImplemented);
1065
+ }
1066
+ setAppMetadata() {
1067
+ throw createClientAuthError(methodNotImplemented);
1068
+ }
1069
+ getAppMetadata() {
1070
+ throw createClientAuthError(methodNotImplemented);
1071
+ }
1072
+ setServerTelemetry() {
1073
+ throw createClientAuthError(methodNotImplemented);
1074
+ }
1075
+ getServerTelemetry() {
1076
+ throw createClientAuthError(methodNotImplemented);
1077
+ }
1078
+ setAuthorityMetadata() {
1079
+ throw createClientAuthError(methodNotImplemented);
1080
+ }
1081
+ getAuthorityMetadata() {
1082
+ throw createClientAuthError(methodNotImplemented);
1083
+ }
1084
+ getAuthorityMetadataKeys() {
1085
+ throw createClientAuthError(methodNotImplemented);
1086
+ }
1087
+ setThrottlingCache() {
1088
+ throw createClientAuthError(methodNotImplemented);
1089
+ }
1090
+ getThrottlingCache() {
1091
+ throw createClientAuthError(methodNotImplemented);
1092
+ }
1093
+ removeItem() {
1094
+ throw createClientAuthError(methodNotImplemented);
1095
+ }
1096
+ containsKey() {
1097
+ throw createClientAuthError(methodNotImplemented);
1098
+ }
1099
+ getKeys() {
1100
+ throw createClientAuthError(methodNotImplemented);
1101
+ }
1102
+ getAccountKeys() {
1103
+ throw createClientAuthError(methodNotImplemented);
1104
+ }
1105
+ getTokenKeys() {
1106
+ throw createClientAuthError(methodNotImplemented);
1107
+ }
1108
+ async clear() {
1109
+ throw createClientAuthError(methodNotImplemented);
1110
+ }
1111
+ updateCredentialCacheKey() {
1112
+ throw createClientAuthError(methodNotImplemented);
1113
+ }
1101
1114
  }
1102
1115
 
1103
1116
  export { CacheManager, DefaultStorageClass };