@azure/msal-common 14.0.0-alpha.1 → 14.0.0-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 (187) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +62 -62
  3. package/dist/account/AccountInfo.d.ts +31 -31
  4. package/dist/account/AuthToken.d.ts +20 -20
  5. package/dist/account/AuthToken.js +48 -48
  6. package/dist/account/CcsCredential.d.ts +9 -8
  7. package/dist/account/CcsCredential.d.ts.map +1 -1
  8. package/dist/account/CcsCredential.js +9 -10
  9. package/dist/account/CcsCredential.js.map +1 -1
  10. package/dist/account/ClientCredentials.d.ts +14 -14
  11. package/dist/account/ClientInfo.d.ts +19 -19
  12. package/dist/account/ClientInfo.js +37 -37
  13. package/dist/account/DecodedAuthToken.d.ts +8 -8
  14. package/dist/account/TokenClaims.d.ts +65 -65
  15. package/dist/authority/Authority.d.ts +228 -215
  16. package/dist/authority/Authority.d.ts.map +1 -1
  17. package/dist/authority/Authority.js +716 -682
  18. package/dist/authority/Authority.js.map +1 -1
  19. package/dist/authority/AuthorityFactory.d.ts +30 -30
  20. package/dist/authority/AuthorityFactory.js +47 -47
  21. package/dist/authority/AuthorityMetadata.d.ts +622 -622
  22. package/dist/authority/AuthorityMetadata.js +876 -876
  23. package/dist/authority/AuthorityOptions.d.ts +19 -18
  24. package/dist/authority/AuthorityOptions.d.ts.map +1 -1
  25. package/dist/authority/AuthorityOptions.js +19 -20
  26. package/dist/authority/AuthorityOptions.js.map +1 -1
  27. package/dist/authority/AuthorityType.d.ts +10 -9
  28. package/dist/authority/AuthorityType.d.ts.map +1 -1
  29. package/dist/authority/AuthorityType.js +14 -15
  30. package/dist/authority/AuthorityType.js.map +1 -1
  31. package/dist/authority/AzureRegion.d.ts +1 -1
  32. package/dist/authority/AzureRegionConfiguration.d.ts +5 -5
  33. package/dist/authority/CloudDiscoveryMetadata.d.ts +5 -5
  34. package/dist/authority/CloudInstanceDiscoveryErrorResponse.d.ts +13 -13
  35. package/dist/authority/CloudInstanceDiscoveryErrorResponse.js +8 -8
  36. package/dist/authority/CloudInstanceDiscoveryResponse.d.ts +9 -9
  37. package/dist/authority/CloudInstanceDiscoveryResponse.js +8 -8
  38. package/dist/authority/ImdsOptions.d.ts +5 -5
  39. package/dist/authority/OpenIdConfigResponse.d.ts +11 -11
  40. package/dist/authority/OpenIdConfigResponse.js +10 -10
  41. package/dist/authority/ProtocolMode.d.ts +8 -7
  42. package/dist/authority/ProtocolMode.d.ts.map +1 -1
  43. package/dist/authority/ProtocolMode.js +12 -13
  44. package/dist/authority/ProtocolMode.js.map +1 -1
  45. package/dist/authority/RegionDiscovery.d.ts +30 -30
  46. package/dist/authority/RegionDiscovery.js +108 -108
  47. package/dist/authority/RegionDiscoveryMetadata.d.ts +6 -6
  48. package/dist/broker/nativeBroker/INativeBrokerPlugin.d.ts +15 -15
  49. package/dist/cache/CacheManager.d.ts +443 -443
  50. package/dist/cache/CacheManager.js +1011 -1011
  51. package/dist/cache/entities/AccessTokenEntity.d.ts +56 -56
  52. package/dist/cache/entities/AccessTokenEntity.js +111 -111
  53. package/dist/cache/entities/AccountEntity.d.ts +99 -99
  54. package/dist/cache/entities/AccountEntity.js +248 -248
  55. package/dist/cache/entities/AppMetadataEntity.d.ts +39 -39
  56. package/dist/cache/entities/AppMetadataEntity.js +66 -66
  57. package/dist/cache/entities/AuthorityMetadataEntity.d.ts +47 -47
  58. package/dist/cache/entities/AuthorityMetadataEntity.js +77 -77
  59. package/dist/cache/entities/CacheRecord.d.ts +13 -13
  60. package/dist/cache/entities/CacheRecord.js +13 -13
  61. package/dist/cache/entities/CredentialEntity.d.ts +88 -88
  62. package/dist/cache/entities/CredentialEntity.js +136 -136
  63. package/dist/cache/entities/IdTokenEntity.d.ts +34 -34
  64. package/dist/cache/entities/IdTokenEntity.js +56 -56
  65. package/dist/cache/entities/RefreshTokenEntity.d.ts +36 -36
  66. package/dist/cache/entities/RefreshTokenEntity.js +59 -59
  67. package/dist/cache/entities/ServerTelemetryEntity.d.ts +12 -12
  68. package/dist/cache/entities/ServerTelemetryEntity.js +27 -27
  69. package/dist/cache/entities/ThrottlingEntity.d.ts +13 -13
  70. package/dist/cache/entities/ThrottlingEntity.js +23 -23
  71. package/dist/cache/interface/ICacheManager.d.ts +165 -165
  72. package/dist/cache/interface/ICachePlugin.d.ts +5 -5
  73. package/dist/cache/interface/ISerializableTokenCache.d.ts +4 -4
  74. package/dist/cache/persistence/TokenCacheContext.d.ts +23 -23
  75. package/dist/cache/persistence/TokenCacheContext.js +25 -25
  76. package/dist/cache/utils/CacheTypes.d.ts +62 -62
  77. package/dist/client/AuthorizationCodeClient.d.ts +71 -71
  78. package/dist/client/AuthorizationCodeClient.js +433 -433
  79. package/dist/client/BaseClient.d.ts +50 -50
  80. package/dist/client/BaseClient.js +92 -92
  81. package/dist/client/RefreshTokenClient.d.ts +34 -34
  82. package/dist/client/RefreshTokenClient.js +239 -239
  83. package/dist/client/SilentFlowClient.d.ts +24 -24
  84. package/dist/client/SilentFlowClient.js +94 -94
  85. package/dist/config/AppTokenProvider.d.ts +38 -38
  86. package/dist/config/ClientConfiguration.d.ts +133 -133
  87. package/dist/config/ClientConfiguration.js +88 -88
  88. package/dist/crypto/ICrypto.d.ts +62 -62
  89. package/dist/crypto/ICrypto.js +42 -42
  90. package/dist/crypto/IGuidGenerator.d.ts +4 -4
  91. package/dist/crypto/JoseHeader.d.ts +21 -21
  92. package/dist/crypto/JoseHeader.js +36 -36
  93. package/dist/crypto/PopTokenGenerator.d.ts +58 -57
  94. package/dist/crypto/PopTokenGenerator.d.ts.map +1 -1
  95. package/dist/crypto/PopTokenGenerator.js +82 -83
  96. package/dist/crypto/PopTokenGenerator.js.map +1 -1
  97. package/dist/crypto/SignedHttpRequest.d.ts +11 -11
  98. package/dist/error/AuthError.d.ts +47 -47
  99. package/dist/error/AuthError.js +51 -51
  100. package/dist/error/ClientAuthError.d.ts +412 -412
  101. package/dist/error/ClientAuthError.js +519 -519
  102. package/dist/error/ClientConfigurationError.d.ts +206 -198
  103. package/dist/error/ClientConfigurationError.d.ts.map +1 -1
  104. package/dist/error/ClientConfigurationError.js +259 -249
  105. package/dist/error/ClientConfigurationError.js.map +1 -1
  106. package/dist/error/InteractionRequiredAuthError.d.ts +59 -59
  107. package/dist/error/InteractionRequiredAuthError.js +78 -78
  108. package/dist/error/JoseHeaderError.d.ts +28 -28
  109. package/dist/error/JoseHeaderError.js +39 -39
  110. package/dist/error/ServerError.d.ts +7 -7
  111. package/dist/error/ServerError.js +14 -14
  112. package/dist/index.cjs.js +8826 -8813
  113. package/dist/index.cjs.js.map +1 -1
  114. package/dist/index.d.ts +93 -93
  115. package/dist/index.js +1 -1
  116. package/dist/logger/Logger.d.ts +95 -95
  117. package/dist/logger/Logger.js +197 -197
  118. package/dist/network/INetworkModule.d.ts +29 -29
  119. package/dist/network/INetworkModule.js +14 -14
  120. package/dist/network/NetworkManager.d.ts +32 -32
  121. package/dist/network/NetworkManager.js +33 -33
  122. package/dist/network/RequestThumbprint.d.ts +16 -16
  123. package/dist/network/ThrottlingUtils.d.ts +41 -41
  124. package/dist/network/ThrottlingUtils.js +94 -94
  125. package/dist/packageMetadata.d.ts +2 -2
  126. package/dist/packageMetadata.d.ts.map +1 -1
  127. package/dist/packageMetadata.js +4 -4
  128. package/dist/request/AuthenticationHeaderParser.d.ts +19 -19
  129. package/dist/request/AuthenticationHeaderParser.js +55 -55
  130. package/dist/request/BaseAuthRequest.d.ts +37 -37
  131. package/dist/request/CommonAuthorizationCodeRequest.d.ts +27 -27
  132. package/dist/request/CommonAuthorizationUrlRequest.d.ts +50 -50
  133. package/dist/request/CommonClientCredentialRequest.d.ts +17 -17
  134. package/dist/request/CommonDeviceCodeRequest.d.ts +21 -21
  135. package/dist/request/CommonEndSessionRequest.d.ts +21 -21
  136. package/dist/request/CommonOnBehalfOfRequest.d.ts +13 -13
  137. package/dist/request/CommonRefreshTokenRequest.d.ts +19 -19
  138. package/dist/request/CommonSilentFlowRequest.d.ts +18 -18
  139. package/dist/request/CommonUsernamePasswordRequest.d.ts +17 -17
  140. package/dist/request/NativeRequest.d.ts +19 -19
  141. package/dist/request/NativeSignOutRequest.d.ts +5 -5
  142. package/dist/request/RequestParameterBuilder.d.ts +216 -216
  143. package/dist/request/RequestParameterBuilder.js +374 -374
  144. package/dist/request/RequestValidator.d.ts +33 -33
  145. package/dist/request/RequestValidator.js +82 -83
  146. package/dist/request/RequestValidator.js.map +1 -1
  147. package/dist/request/ScopeSet.d.ts +88 -88
  148. package/dist/request/ScopeSet.js +197 -197
  149. package/dist/response/AuthenticationResult.d.ts +39 -39
  150. package/dist/response/AuthorizationCodePayload.d.ts +13 -13
  151. package/dist/response/DeviceCodeResponse.d.ts +25 -25
  152. package/dist/response/ExternalTokenResponse.d.ts +15 -15
  153. package/dist/response/IMDSBadResponse.d.ts +4 -4
  154. package/dist/response/ResponseHandler.d.ts +72 -72
  155. package/dist/response/ResponseHandler.js +300 -300
  156. package/dist/response/ServerAuthorizationCodeResponse.d.ts +25 -25
  157. package/dist/response/ServerAuthorizationTokenResponse.d.ts +44 -44
  158. package/dist/telemetry/performance/IPerformanceClient.d.ts +42 -42
  159. package/dist/telemetry/performance/IPerformanceMeasurement.d.ts +5 -5
  160. package/dist/telemetry/performance/PerformanceClient.d.ts +189 -189
  161. package/dist/telemetry/performance/PerformanceClient.js +406 -406
  162. package/dist/telemetry/performance/PerformanceEvent.d.ts +441 -439
  163. package/dist/telemetry/performance/PerformanceEvent.d.ts.map +1 -1
  164. package/dist/telemetry/performance/PerformanceEvent.js +225 -227
  165. package/dist/telemetry/performance/PerformanceEvent.js.map +1 -1
  166. package/dist/telemetry/performance/StubPerformanceClient.d.ts +15 -19
  167. package/dist/telemetry/performance/StubPerformanceClient.d.ts.map +1 -1
  168. package/dist/telemetry/performance/StubPerformanceClient.js +22 -36
  169. package/dist/telemetry/performance/StubPerformanceClient.js.map +1 -1
  170. package/dist/telemetry/server/ServerTelemetryManager.d.ts +65 -65
  171. package/dist/telemetry/server/ServerTelemetryManager.js +196 -196
  172. package/dist/telemetry/server/ServerTelemetryRequest.d.ts +8 -8
  173. package/dist/url/IUri.d.ts +12 -12
  174. package/dist/url/UrlString.d.ts +70 -70
  175. package/dist/url/UrlString.js +242 -242
  176. package/dist/utils/Constants.d.ts +345 -331
  177. package/dist/utils/Constants.d.ts.map +1 -1
  178. package/dist/utils/Constants.js +353 -373
  179. package/dist/utils/Constants.js.map +1 -1
  180. package/dist/utils/MsalTypes.d.ts +6 -6
  181. package/dist/utils/ProtocolUtils.d.ts +42 -42
  182. package/dist/utils/ProtocolUtils.js +71 -71
  183. package/dist/utils/StringUtils.d.ts +53 -53
  184. package/dist/utils/StringUtils.js +124 -124
  185. package/dist/utils/TimeUtils.d.ts +27 -27
  186. package/dist/utils/TimeUtils.js +45 -45
  187. package/package.json +86 -79
@@ -1,4 +1,4 @@
1
- /*! @azure/msal-common v14.0.0-alpha.1 2023-05-08 */
1
+ /*! @azure/msal-common v14.0.0-beta.0 2023-06-19 */
2
2
  'use strict';
3
3
  import { buildClientInfo } from '../account/ClientInfo.js';
4
4
  import { ClientAuthError } from '../error/ClientAuthError.js';
@@ -20,305 +20,305 @@ import { AppMetadataEntity } from '../cache/entities/AppMetadataEntity.js';
20
20
  import { TokenCacheContext } from '../cache/persistence/TokenCacheContext.js';
21
21
  import { PerformanceEvents } from '../telemetry/performance/PerformanceEvent.js';
22
22
 
23
- /*
24
- * Copyright (c) Microsoft Corporation. All rights reserved.
25
- * Licensed under the MIT License.
26
- */
27
- /**
28
- * Class that handles response parsing.
29
- */
30
- class ResponseHandler {
31
- constructor(clientId, cacheStorage, cryptoObj, logger, serializableCache, persistencePlugin, performanceClient) {
32
- this.clientId = clientId;
33
- this.cacheStorage = cacheStorage;
34
- this.cryptoObj = cryptoObj;
35
- this.logger = logger;
36
- this.serializableCache = serializableCache;
37
- this.persistencePlugin = persistencePlugin;
38
- this.performanceClient = performanceClient;
39
- }
40
- /**
41
- * Function which validates server authorization code response.
42
- * @param serverResponseHash
43
- * @param cachedState
44
- * @param cryptoObj
45
- */
46
- validateServerAuthorizationCodeResponse(serverResponseHash, cachedState, cryptoObj) {
47
- if (!serverResponseHash.state || !cachedState) {
48
- throw !serverResponseHash.state
49
- ? ClientAuthError.createStateNotFoundError("Server State")
50
- : ClientAuthError.createStateNotFoundError("Cached State");
51
- }
52
- if (decodeURIComponent(serverResponseHash.state) !==
53
- decodeURIComponent(cachedState)) {
54
- throw ClientAuthError.createStateMismatchError();
55
- }
56
- // Check for error
57
- if (serverResponseHash.error ||
58
- serverResponseHash.error_description ||
59
- serverResponseHash.suberror) {
60
- if (InteractionRequiredAuthError.isInteractionRequiredError(serverResponseHash.error, serverResponseHash.error_description, serverResponseHash.suberror)) {
61
- throw new InteractionRequiredAuthError(serverResponseHash.error || Constants.EMPTY_STRING, serverResponseHash.error_description, serverResponseHash.suberror, serverResponseHash.timestamp || Constants.EMPTY_STRING, serverResponseHash.trace_id || Constants.EMPTY_STRING, serverResponseHash.correlation_id || Constants.EMPTY_STRING, serverResponseHash.claims || Constants.EMPTY_STRING);
62
- }
63
- throw new ServerError(serverResponseHash.error || Constants.EMPTY_STRING, serverResponseHash.error_description, serverResponseHash.suberror);
64
- }
65
- if (serverResponseHash.client_info) {
66
- buildClientInfo(serverResponseHash.client_info, cryptoObj);
67
- }
68
- }
69
- /**
70
- * Function which validates server authorization token response.
71
- * @param serverResponse
72
- */
73
- validateTokenResponse(serverResponse) {
74
- // Check for error
75
- if (serverResponse.error ||
76
- serverResponse.error_description ||
77
- serverResponse.suberror) {
78
- if (InteractionRequiredAuthError.isInteractionRequiredError(serverResponse.error, serverResponse.error_description, serverResponse.suberror)) {
79
- 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);
80
- }
81
- const errString = `${serverResponse.error_codes} - [${serverResponse.timestamp}]: ${serverResponse.error_description} - Correlation ID: ${serverResponse.correlation_id} - Trace ID: ${serverResponse.trace_id}`;
82
- throw new ServerError(serverResponse.error, errString, serverResponse.suberror);
83
- }
84
- }
85
- /**
86
- * Returns a constructed token response based on given string. Also manages the cache updates and cleanups.
87
- * @param serverTokenResponse
88
- * @param authority
89
- */
90
- async handleServerTokenResponse(serverTokenResponse, authority, reqTimestamp, request, authCodePayload, userAssertionHash, handlingRefreshTokenResponse, forceCacheRefreshTokenResponse, serverRequestId) {
91
- this.performanceClient?.addQueueMeasurement(PerformanceEvents.HandleServerTokenResponse, serverTokenResponse.correlation_id);
92
- // create an idToken object (not entity)
93
- let idTokenObj;
94
- if (serverTokenResponse.id_token) {
95
- idTokenObj = new AuthToken(serverTokenResponse.id_token || Constants.EMPTY_STRING, this.cryptoObj);
96
- // token nonce check (TODO: Add a warning if no nonce is given?)
97
- if (authCodePayload &&
98
- !StringUtils.isEmpty(authCodePayload.nonce)) {
99
- if (idTokenObj.claims.nonce !== authCodePayload.nonce) {
100
- throw ClientAuthError.createNonceMismatchError();
101
- }
102
- }
103
- // token max_age check
104
- if (request.maxAge || request.maxAge === 0) {
105
- const authTime = idTokenObj.claims.auth_time;
106
- if (!authTime) {
107
- throw ClientAuthError.createAuthTimeNotFoundError();
108
- }
109
- AuthToken.checkMaxAge(authTime, request.maxAge);
110
- }
111
- }
112
- // generate homeAccountId
113
- this.homeAccountIdentifier = AccountEntity.generateHomeAccountId(serverTokenResponse.client_info || Constants.EMPTY_STRING, authority.authorityType, this.logger, this.cryptoObj, idTokenObj);
114
- // save the response tokens
115
- let requestStateObj;
116
- if (!!authCodePayload && !!authCodePayload.state) {
117
- requestStateObj = ProtocolUtils.parseRequestState(this.cryptoObj, authCodePayload.state);
118
- }
119
- // Add keyId from request to serverTokenResponse if defined
120
- serverTokenResponse.key_id =
121
- serverTokenResponse.key_id || request.sshKid || undefined;
122
- const cacheRecord = this.generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenObj, userAssertionHash, authCodePayload);
123
- let cacheContext;
124
- try {
125
- if (this.persistencePlugin && this.serializableCache) {
126
- this.logger.verbose("Persistence enabled, calling beforeCacheAccess");
127
- cacheContext = new TokenCacheContext(this.serializableCache, true);
128
- await this.persistencePlugin.beforeCacheAccess(cacheContext);
129
- }
130
- /*
131
- * When saving a refreshed tokens to the cache, it is expected that the account that was used is present in the cache.
132
- * If not present, we should return null, as it's the case that another application called removeAccount in between
133
- * the calls to getAllAccounts and acquireTokenSilent. We should not overwrite that removal, unless explicitly flagged by
134
- * the developer, as in the case of refresh token flow used in ADAL Node to MSAL Node migration.
135
- */
136
- if (handlingRefreshTokenResponse &&
137
- !forceCacheRefreshTokenResponse &&
138
- cacheRecord.account) {
139
- const key = cacheRecord.account.generateAccountKey();
140
- const account = this.cacheStorage.getAccount(key);
141
- if (!account) {
142
- this.logger.warning("Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache");
143
- return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenObj, requestStateObj, undefined, serverRequestId);
144
- }
145
- }
146
- await this.cacheStorage.saveCacheRecord(cacheRecord);
147
- }
148
- finally {
149
- if (this.persistencePlugin &&
150
- this.serializableCache &&
151
- cacheContext) {
152
- this.logger.verbose("Persistence enabled, calling afterCacheAccess");
153
- await this.persistencePlugin.afterCacheAccess(cacheContext);
154
- }
155
- }
156
- return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenObj, requestStateObj, serverTokenResponse, serverRequestId);
157
- }
158
- /**
159
- * Generates CacheRecord
160
- * @param serverTokenResponse
161
- * @param idTokenObj
162
- * @param authority
163
- */
164
- generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenObj, userAssertionHash, authCodePayload) {
165
- const env = authority.getPreferredCache();
166
- if (StringUtils.isEmpty(env)) {
167
- throw ClientAuthError.createInvalidCacheEnvironmentError();
168
- }
169
- // IdToken: non AAD scenarios can have empty realm
170
- let cachedIdToken;
171
- let cachedAccount;
172
- if (!StringUtils.isEmpty(serverTokenResponse.id_token) &&
173
- !!idTokenObj) {
174
- cachedIdToken = IdTokenEntity.createIdTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.id_token || Constants.EMPTY_STRING, this.clientId, idTokenObj.claims.tid || Constants.EMPTY_STRING);
175
- cachedAccount = this.generateAccountEntity(serverTokenResponse, idTokenObj, authority, authCodePayload);
176
- }
177
- // AccessToken
178
- let cachedAccessToken = null;
179
- if (!StringUtils.isEmpty(serverTokenResponse.access_token)) {
180
- // If scopes not returned in server response, use request scopes
181
- const responseScopes = serverTokenResponse.scope
182
- ? ScopeSet.fromString(serverTokenResponse.scope)
183
- : new ScopeSet(request.scopes || []);
184
- /*
185
- * Use timestamp calculated before request
186
- * Server may return timestamps as strings, parse to numbers if so.
187
- */
188
- const expiresIn = (typeof serverTokenResponse.expires_in === "string"
189
- ? parseInt(serverTokenResponse.expires_in, 10)
190
- : serverTokenResponse.expires_in) || 0;
191
- const extExpiresIn = (typeof serverTokenResponse.ext_expires_in === "string"
192
- ? parseInt(serverTokenResponse.ext_expires_in, 10)
193
- : serverTokenResponse.ext_expires_in) || 0;
194
- const refreshIn = (typeof serverTokenResponse.refresh_in === "string"
195
- ? parseInt(serverTokenResponse.refresh_in, 10)
196
- : serverTokenResponse.refresh_in) || undefined;
197
- const tokenExpirationSeconds = reqTimestamp + expiresIn;
198
- const extendedTokenExpirationSeconds = tokenExpirationSeconds + extExpiresIn;
199
- const refreshOnSeconds = refreshIn && refreshIn > 0
200
- ? reqTimestamp + refreshIn
201
- : undefined;
202
- // non AAD scenarios can have empty realm
203
- cachedAccessToken = AccessTokenEntity.createAccessTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.access_token || Constants.EMPTY_STRING, this.clientId, idTokenObj
204
- ? idTokenObj.claims.tid || Constants.EMPTY_STRING
205
- : authority.tenant, responseScopes.printScopes(), tokenExpirationSeconds, extendedTokenExpirationSeconds, this.cryptoObj, refreshOnSeconds, serverTokenResponse.token_type, userAssertionHash, serverTokenResponse.key_id, request.claims, request.requestedClaimsHash);
206
- }
207
- // refreshToken
208
- let cachedRefreshToken = null;
209
- if (!StringUtils.isEmpty(serverTokenResponse.refresh_token)) {
210
- cachedRefreshToken = RefreshTokenEntity.createRefreshTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.refresh_token || Constants.EMPTY_STRING, this.clientId, serverTokenResponse.foci, userAssertionHash);
211
- }
212
- // appMetadata
213
- let cachedAppMetadata = null;
214
- if (!StringUtils.isEmpty(serverTokenResponse.foci)) {
215
- cachedAppMetadata = AppMetadataEntity.createAppMetadataEntity(this.clientId, env, serverTokenResponse.foci);
216
- }
217
- return new CacheRecord(cachedAccount, cachedIdToken, cachedAccessToken, cachedRefreshToken, cachedAppMetadata);
218
- }
219
- /**
220
- * Generate Account
221
- * @param serverTokenResponse
222
- * @param idToken
223
- * @param authority
224
- */
225
- generateAccountEntity(serverTokenResponse, idToken, authority, authCodePayload) {
226
- const authorityType = authority.authorityType;
227
- const cloudGraphHostName = authCodePayload
228
- ? authCodePayload.cloud_graph_host_name
229
- : Constants.EMPTY_STRING;
230
- const msGraphhost = authCodePayload
231
- ? authCodePayload.msgraph_host
232
- : Constants.EMPTY_STRING;
233
- // ADFS does not require client_info in the response
234
- if (authorityType === AuthorityType.Adfs) {
235
- this.logger.verbose("Authority type is ADFS, creating ADFS account");
236
- return AccountEntity.createGenericAccount(this.homeAccountIdentifier, idToken, authority, cloudGraphHostName, msGraphhost);
237
- }
238
- // This fallback applies to B2C as well as they fall under an AAD account type.
239
- if (StringUtils.isEmpty(serverTokenResponse.client_info) &&
240
- authority.protocolMode === "AAD") {
241
- throw ClientAuthError.createClientInfoEmptyError();
242
- }
243
- return serverTokenResponse.client_info
244
- ? AccountEntity.createAccount(serverTokenResponse.client_info, this.homeAccountIdentifier, idToken, authority, cloudGraphHostName, msGraphhost)
245
- : AccountEntity.createGenericAccount(this.homeAccountIdentifier, idToken, authority, cloudGraphHostName, msGraphhost);
246
- }
247
- /**
248
- * Creates an @AuthenticationResult from @CacheRecord , @IdToken , and a boolean that states whether or not the result is from cache.
249
- *
250
- * Optionally takes a state string that is set as-is in the response.
251
- *
252
- * @param cacheRecord
253
- * @param idTokenObj
254
- * @param fromTokenCache
255
- * @param stateString
256
- */
257
- static async generateAuthenticationResult(cryptoObj, authority, cacheRecord, fromTokenCache, request, idTokenObj, requestState, serverTokenResponse, requestId) {
258
- let accessToken = Constants.EMPTY_STRING;
259
- let responseScopes = [];
260
- let expiresOn = null;
261
- let extExpiresOn;
262
- let familyId = Constants.EMPTY_STRING;
263
- if (cacheRecord.accessToken) {
264
- if (cacheRecord.accessToken.tokenType === AuthenticationScheme.POP) {
265
- const popTokenGenerator = new PopTokenGenerator(cryptoObj);
266
- const { secret, keyId } = cacheRecord.accessToken;
267
- if (!keyId) {
268
- throw ClientAuthError.createKeyIdMissingError();
269
- }
270
- accessToken = await popTokenGenerator.signPopToken(secret, keyId, request);
271
- }
272
- else {
273
- accessToken = cacheRecord.accessToken.secret;
274
- }
275
- responseScopes = ScopeSet.fromString(cacheRecord.accessToken.target).asArray();
276
- expiresOn = new Date(Number(cacheRecord.accessToken.expiresOn) * 1000);
277
- extExpiresOn = new Date(Number(cacheRecord.accessToken.extendedExpiresOn) * 1000);
278
- }
279
- if (cacheRecord.appMetadata) {
280
- familyId =
281
- cacheRecord.appMetadata.familyId === THE_FAMILY_ID
282
- ? THE_FAMILY_ID
283
- : Constants.EMPTY_STRING;
284
- }
285
- const uid = idTokenObj?.claims.oid ||
286
- idTokenObj?.claims.sub ||
287
- Constants.EMPTY_STRING;
288
- const tid = idTokenObj?.claims.tid || Constants.EMPTY_STRING;
289
- // for hybrid + native bridge enablement, send back the native account Id
290
- if (serverTokenResponse?.spa_accountid && !!cacheRecord.account) {
291
- cacheRecord.account.nativeAccountId =
292
- serverTokenResponse?.spa_accountid;
293
- }
294
- return {
295
- authority: authority.canonicalAuthority,
296
- uniqueId: uid,
297
- tenantId: tid,
298
- scopes: responseScopes,
299
- account: cacheRecord.account
300
- ? cacheRecord.account.getAccountInfo()
301
- : null,
302
- idToken: idTokenObj ? idTokenObj.rawToken : Constants.EMPTY_STRING,
303
- idTokenClaims: idTokenObj ? idTokenObj.claims : {},
304
- accessToken: accessToken,
305
- fromCache: fromTokenCache,
306
- expiresOn: expiresOn,
307
- correlationId: request.correlationId,
308
- requestId: requestId || Constants.EMPTY_STRING,
309
- extExpiresOn: extExpiresOn,
310
- familyId: familyId,
311
- tokenType: cacheRecord.accessToken?.tokenType || Constants.EMPTY_STRING,
312
- state: requestState
313
- ? requestState.userRequestState
314
- : Constants.EMPTY_STRING,
315
- cloudGraphHostName: cacheRecord.account?.cloudGraphHostName ||
316
- Constants.EMPTY_STRING,
317
- msGraphHost: cacheRecord.account?.msGraphHost || Constants.EMPTY_STRING,
318
- code: serverTokenResponse?.spa_code,
319
- fromNativeBroker: false,
320
- };
321
- }
23
+ /*
24
+ * Copyright (c) Microsoft Corporation. All rights reserved.
25
+ * Licensed under the MIT License.
26
+ */
27
+ /**
28
+ * Class that handles response parsing.
29
+ */
30
+ class ResponseHandler {
31
+ constructor(clientId, cacheStorage, cryptoObj, logger, serializableCache, persistencePlugin, performanceClient) {
32
+ this.clientId = clientId;
33
+ this.cacheStorage = cacheStorage;
34
+ this.cryptoObj = cryptoObj;
35
+ this.logger = logger;
36
+ this.serializableCache = serializableCache;
37
+ this.persistencePlugin = persistencePlugin;
38
+ this.performanceClient = performanceClient;
39
+ }
40
+ /**
41
+ * Function which validates server authorization code response.
42
+ * @param serverResponseHash
43
+ * @param cachedState
44
+ * @param cryptoObj
45
+ */
46
+ validateServerAuthorizationCodeResponse(serverResponseHash, cachedState, cryptoObj) {
47
+ if (!serverResponseHash.state || !cachedState) {
48
+ throw !serverResponseHash.state
49
+ ? ClientAuthError.createStateNotFoundError("Server State")
50
+ : ClientAuthError.createStateNotFoundError("Cached State");
51
+ }
52
+ if (decodeURIComponent(serverResponseHash.state) !==
53
+ decodeURIComponent(cachedState)) {
54
+ throw ClientAuthError.createStateMismatchError();
55
+ }
56
+ // Check for error
57
+ if (serverResponseHash.error ||
58
+ serverResponseHash.error_description ||
59
+ serverResponseHash.suberror) {
60
+ if (InteractionRequiredAuthError.isInteractionRequiredError(serverResponseHash.error, serverResponseHash.error_description, serverResponseHash.suberror)) {
61
+ throw new InteractionRequiredAuthError(serverResponseHash.error || Constants.EMPTY_STRING, serverResponseHash.error_description, serverResponseHash.suberror, serverResponseHash.timestamp || Constants.EMPTY_STRING, serverResponseHash.trace_id || Constants.EMPTY_STRING, serverResponseHash.correlation_id || Constants.EMPTY_STRING, serverResponseHash.claims || Constants.EMPTY_STRING);
62
+ }
63
+ throw new ServerError(serverResponseHash.error || Constants.EMPTY_STRING, serverResponseHash.error_description, serverResponseHash.suberror);
64
+ }
65
+ if (serverResponseHash.client_info) {
66
+ buildClientInfo(serverResponseHash.client_info, cryptoObj);
67
+ }
68
+ }
69
+ /**
70
+ * Function which validates server authorization token response.
71
+ * @param serverResponse
72
+ */
73
+ validateTokenResponse(serverResponse) {
74
+ // Check for error
75
+ if (serverResponse.error ||
76
+ serverResponse.error_description ||
77
+ serverResponse.suberror) {
78
+ if (InteractionRequiredAuthError.isInteractionRequiredError(serverResponse.error, serverResponse.error_description, serverResponse.suberror)) {
79
+ 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);
80
+ }
81
+ const errString = `${serverResponse.error_codes} - [${serverResponse.timestamp}]: ${serverResponse.error_description} - Correlation ID: ${serverResponse.correlation_id} - Trace ID: ${serverResponse.trace_id}`;
82
+ throw new ServerError(serverResponse.error, errString, serverResponse.suberror);
83
+ }
84
+ }
85
+ /**
86
+ * Returns a constructed token response based on given string. Also manages the cache updates and cleanups.
87
+ * @param serverTokenResponse
88
+ * @param authority
89
+ */
90
+ async handleServerTokenResponse(serverTokenResponse, authority, reqTimestamp, request, authCodePayload, userAssertionHash, handlingRefreshTokenResponse, forceCacheRefreshTokenResponse, serverRequestId) {
91
+ this.performanceClient?.addQueueMeasurement(PerformanceEvents.HandleServerTokenResponse, serverTokenResponse.correlation_id);
92
+ // create an idToken object (not entity)
93
+ let idTokenObj;
94
+ if (serverTokenResponse.id_token) {
95
+ idTokenObj = new AuthToken(serverTokenResponse.id_token || Constants.EMPTY_STRING, this.cryptoObj);
96
+ // token nonce check (TODO: Add a warning if no nonce is given?)
97
+ if (authCodePayload &&
98
+ !StringUtils.isEmpty(authCodePayload.nonce)) {
99
+ if (idTokenObj.claims.nonce !== authCodePayload.nonce) {
100
+ throw ClientAuthError.createNonceMismatchError();
101
+ }
102
+ }
103
+ // token max_age check
104
+ if (request.maxAge || request.maxAge === 0) {
105
+ const authTime = idTokenObj.claims.auth_time;
106
+ if (!authTime) {
107
+ throw ClientAuthError.createAuthTimeNotFoundError();
108
+ }
109
+ AuthToken.checkMaxAge(authTime, request.maxAge);
110
+ }
111
+ }
112
+ // generate homeAccountId
113
+ this.homeAccountIdentifier = AccountEntity.generateHomeAccountId(serverTokenResponse.client_info || Constants.EMPTY_STRING, authority.authorityType, this.logger, this.cryptoObj, idTokenObj);
114
+ // save the response tokens
115
+ let requestStateObj;
116
+ if (!!authCodePayload && !!authCodePayload.state) {
117
+ requestStateObj = ProtocolUtils.parseRequestState(this.cryptoObj, authCodePayload.state);
118
+ }
119
+ // Add keyId from request to serverTokenResponse if defined
120
+ serverTokenResponse.key_id =
121
+ serverTokenResponse.key_id || request.sshKid || undefined;
122
+ const cacheRecord = this.generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenObj, userAssertionHash, authCodePayload);
123
+ let cacheContext;
124
+ try {
125
+ if (this.persistencePlugin && this.serializableCache) {
126
+ this.logger.verbose("Persistence enabled, calling beforeCacheAccess");
127
+ cacheContext = new TokenCacheContext(this.serializableCache, true);
128
+ await this.persistencePlugin.beforeCacheAccess(cacheContext);
129
+ }
130
+ /*
131
+ * When saving a refreshed tokens to the cache, it is expected that the account that was used is present in the cache.
132
+ * If not present, we should return null, as it's the case that another application called removeAccount in between
133
+ * the calls to getAllAccounts and acquireTokenSilent. We should not overwrite that removal, unless explicitly flagged by
134
+ * the developer, as in the case of refresh token flow used in ADAL Node to MSAL Node migration.
135
+ */
136
+ if (handlingRefreshTokenResponse &&
137
+ !forceCacheRefreshTokenResponse &&
138
+ cacheRecord.account) {
139
+ const key = cacheRecord.account.generateAccountKey();
140
+ const account = this.cacheStorage.getAccount(key);
141
+ if (!account) {
142
+ this.logger.warning("Account used to refresh tokens not in persistence, refreshed tokens will not be stored in the cache");
143
+ return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenObj, requestStateObj, undefined, serverRequestId);
144
+ }
145
+ }
146
+ await this.cacheStorage.saveCacheRecord(cacheRecord);
147
+ }
148
+ finally {
149
+ if (this.persistencePlugin &&
150
+ this.serializableCache &&
151
+ cacheContext) {
152
+ this.logger.verbose("Persistence enabled, calling afterCacheAccess");
153
+ await this.persistencePlugin.afterCacheAccess(cacheContext);
154
+ }
155
+ }
156
+ return ResponseHandler.generateAuthenticationResult(this.cryptoObj, authority, cacheRecord, false, request, idTokenObj, requestStateObj, serverTokenResponse, serverRequestId);
157
+ }
158
+ /**
159
+ * Generates CacheRecord
160
+ * @param serverTokenResponse
161
+ * @param idTokenObj
162
+ * @param authority
163
+ */
164
+ generateCacheRecord(serverTokenResponse, authority, reqTimestamp, request, idTokenObj, userAssertionHash, authCodePayload) {
165
+ const env = authority.getPreferredCache();
166
+ if (StringUtils.isEmpty(env)) {
167
+ throw ClientAuthError.createInvalidCacheEnvironmentError();
168
+ }
169
+ // IdToken: non AAD scenarios can have empty realm
170
+ let cachedIdToken;
171
+ let cachedAccount;
172
+ if (!StringUtils.isEmpty(serverTokenResponse.id_token) &&
173
+ !!idTokenObj) {
174
+ cachedIdToken = IdTokenEntity.createIdTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.id_token || Constants.EMPTY_STRING, this.clientId, idTokenObj.claims.tid || Constants.EMPTY_STRING);
175
+ cachedAccount = this.generateAccountEntity(serverTokenResponse, idTokenObj, authority, authCodePayload);
176
+ }
177
+ // AccessToken
178
+ let cachedAccessToken = null;
179
+ if (!StringUtils.isEmpty(serverTokenResponse.access_token)) {
180
+ // If scopes not returned in server response, use request scopes
181
+ const responseScopes = serverTokenResponse.scope
182
+ ? ScopeSet.fromString(serverTokenResponse.scope)
183
+ : new ScopeSet(request.scopes || []);
184
+ /*
185
+ * Use timestamp calculated before request
186
+ * Server may return timestamps as strings, parse to numbers if so.
187
+ */
188
+ const expiresIn = (typeof serverTokenResponse.expires_in === "string"
189
+ ? parseInt(serverTokenResponse.expires_in, 10)
190
+ : serverTokenResponse.expires_in) || 0;
191
+ const extExpiresIn = (typeof serverTokenResponse.ext_expires_in === "string"
192
+ ? parseInt(serverTokenResponse.ext_expires_in, 10)
193
+ : serverTokenResponse.ext_expires_in) || 0;
194
+ const refreshIn = (typeof serverTokenResponse.refresh_in === "string"
195
+ ? parseInt(serverTokenResponse.refresh_in, 10)
196
+ : serverTokenResponse.refresh_in) || undefined;
197
+ const tokenExpirationSeconds = reqTimestamp + expiresIn;
198
+ const extendedTokenExpirationSeconds = tokenExpirationSeconds + extExpiresIn;
199
+ const refreshOnSeconds = refreshIn && refreshIn > 0
200
+ ? reqTimestamp + refreshIn
201
+ : undefined;
202
+ // non AAD scenarios can have empty realm
203
+ cachedAccessToken = AccessTokenEntity.createAccessTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.access_token || Constants.EMPTY_STRING, this.clientId, idTokenObj
204
+ ? idTokenObj.claims.tid || Constants.EMPTY_STRING
205
+ : authority.tenant, responseScopes.printScopes(), tokenExpirationSeconds, extendedTokenExpirationSeconds, this.cryptoObj, refreshOnSeconds, serverTokenResponse.token_type, userAssertionHash, serverTokenResponse.key_id, request.claims, request.requestedClaimsHash);
206
+ }
207
+ // refreshToken
208
+ let cachedRefreshToken = null;
209
+ if (!StringUtils.isEmpty(serverTokenResponse.refresh_token)) {
210
+ cachedRefreshToken = RefreshTokenEntity.createRefreshTokenEntity(this.homeAccountIdentifier, env, serverTokenResponse.refresh_token || Constants.EMPTY_STRING, this.clientId, serverTokenResponse.foci, userAssertionHash);
211
+ }
212
+ // appMetadata
213
+ let cachedAppMetadata = null;
214
+ if (!StringUtils.isEmpty(serverTokenResponse.foci)) {
215
+ cachedAppMetadata = AppMetadataEntity.createAppMetadataEntity(this.clientId, env, serverTokenResponse.foci);
216
+ }
217
+ return new CacheRecord(cachedAccount, cachedIdToken, cachedAccessToken, cachedRefreshToken, cachedAppMetadata);
218
+ }
219
+ /**
220
+ * Generate Account
221
+ * @param serverTokenResponse
222
+ * @param idToken
223
+ * @param authority
224
+ */
225
+ generateAccountEntity(serverTokenResponse, idToken, authority, authCodePayload) {
226
+ const authorityType = authority.authorityType;
227
+ const cloudGraphHostName = authCodePayload
228
+ ? authCodePayload.cloud_graph_host_name
229
+ : Constants.EMPTY_STRING;
230
+ const msGraphhost = authCodePayload
231
+ ? authCodePayload.msgraph_host
232
+ : Constants.EMPTY_STRING;
233
+ // ADFS does not require client_info in the response
234
+ if (authorityType === AuthorityType.Adfs) {
235
+ this.logger.verbose("Authority type is ADFS, creating ADFS account");
236
+ return AccountEntity.createGenericAccount(this.homeAccountIdentifier, idToken, authority, cloudGraphHostName, msGraphhost);
237
+ }
238
+ // This fallback applies to B2C as well as they fall under an AAD account type.
239
+ if (StringUtils.isEmpty(serverTokenResponse.client_info) &&
240
+ authority.protocolMode === "AAD") {
241
+ throw ClientAuthError.createClientInfoEmptyError();
242
+ }
243
+ return serverTokenResponse.client_info
244
+ ? AccountEntity.createAccount(serverTokenResponse.client_info, this.homeAccountIdentifier, idToken, authority, cloudGraphHostName, msGraphhost)
245
+ : AccountEntity.createGenericAccount(this.homeAccountIdentifier, idToken, authority, cloudGraphHostName, msGraphhost);
246
+ }
247
+ /**
248
+ * Creates an @AuthenticationResult from @CacheRecord , @IdToken , and a boolean that states whether or not the result is from cache.
249
+ *
250
+ * Optionally takes a state string that is set as-is in the response.
251
+ *
252
+ * @param cacheRecord
253
+ * @param idTokenObj
254
+ * @param fromTokenCache
255
+ * @param stateString
256
+ */
257
+ static async generateAuthenticationResult(cryptoObj, authority, cacheRecord, fromTokenCache, request, idTokenObj, requestState, serverTokenResponse, requestId) {
258
+ let accessToken = Constants.EMPTY_STRING;
259
+ let responseScopes = [];
260
+ let expiresOn = null;
261
+ let extExpiresOn;
262
+ let familyId = Constants.EMPTY_STRING;
263
+ if (cacheRecord.accessToken) {
264
+ if (cacheRecord.accessToken.tokenType === AuthenticationScheme.POP) {
265
+ const popTokenGenerator = new PopTokenGenerator(cryptoObj);
266
+ const { secret, keyId } = cacheRecord.accessToken;
267
+ if (!keyId) {
268
+ throw ClientAuthError.createKeyIdMissingError();
269
+ }
270
+ accessToken = await popTokenGenerator.signPopToken(secret, keyId, request);
271
+ }
272
+ else {
273
+ accessToken = cacheRecord.accessToken.secret;
274
+ }
275
+ responseScopes = ScopeSet.fromString(cacheRecord.accessToken.target).asArray();
276
+ expiresOn = new Date(Number(cacheRecord.accessToken.expiresOn) * 1000);
277
+ extExpiresOn = new Date(Number(cacheRecord.accessToken.extendedExpiresOn) * 1000);
278
+ }
279
+ if (cacheRecord.appMetadata) {
280
+ familyId =
281
+ cacheRecord.appMetadata.familyId === THE_FAMILY_ID
282
+ ? THE_FAMILY_ID
283
+ : Constants.EMPTY_STRING;
284
+ }
285
+ const uid = idTokenObj?.claims.oid ||
286
+ idTokenObj?.claims.sub ||
287
+ Constants.EMPTY_STRING;
288
+ const tid = idTokenObj?.claims.tid || Constants.EMPTY_STRING;
289
+ // for hybrid + native bridge enablement, send back the native account Id
290
+ if (serverTokenResponse?.spa_accountid && !!cacheRecord.account) {
291
+ cacheRecord.account.nativeAccountId =
292
+ serverTokenResponse?.spa_accountid;
293
+ }
294
+ return {
295
+ authority: authority.canonicalAuthority,
296
+ uniqueId: uid,
297
+ tenantId: tid,
298
+ scopes: responseScopes,
299
+ account: cacheRecord.account
300
+ ? cacheRecord.account.getAccountInfo()
301
+ : null,
302
+ idToken: idTokenObj ? idTokenObj.rawToken : Constants.EMPTY_STRING,
303
+ idTokenClaims: idTokenObj ? idTokenObj.claims : {},
304
+ accessToken: accessToken,
305
+ fromCache: fromTokenCache,
306
+ expiresOn: expiresOn,
307
+ correlationId: request.correlationId,
308
+ requestId: requestId || Constants.EMPTY_STRING,
309
+ extExpiresOn: extExpiresOn,
310
+ familyId: familyId,
311
+ tokenType: cacheRecord.accessToken?.tokenType || Constants.EMPTY_STRING,
312
+ state: requestState
313
+ ? requestState.userRequestState
314
+ : Constants.EMPTY_STRING,
315
+ cloudGraphHostName: cacheRecord.account?.cloudGraphHostName ||
316
+ Constants.EMPTY_STRING,
317
+ msGraphHost: cacheRecord.account?.msGraphHost || Constants.EMPTY_STRING,
318
+ code: serverTokenResponse?.spa_code,
319
+ fromNativeBroker: false,
320
+ };
321
+ }
322
322
  }
323
323
 
324
324
  export { ResponseHandler };