@azure/msal-common 16.14.3 → 16.16.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 (235) hide show
  1. package/dist/account/AccountInfo.mjs +1 -1
  2. package/dist/account/AuthToken.mjs +1 -1
  3. package/dist/account/CcsCredential.mjs +1 -1
  4. package/dist/account/ClientInfo.mjs +1 -1
  5. package/dist/account/TokenClaims.mjs +1 -1
  6. package/dist/authority/Authority.mjs +1 -1
  7. package/dist/authority/AuthorityFactory.mjs +1 -1
  8. package/dist/authority/AuthorityMetadata.mjs +1 -1
  9. package/dist/authority/AuthorityOptions.mjs +1 -1
  10. package/dist/authority/AuthorityType.mjs +1 -1
  11. package/dist/authority/CloudInstanceDiscoveryErrorResponse.mjs +1 -1
  12. package/dist/authority/CloudInstanceDiscoveryResponse.mjs +1 -1
  13. package/dist/authority/OpenIdConfigResponse.mjs +1 -1
  14. package/dist/authority/ProtocolMode.mjs +1 -1
  15. package/dist/authority/RegionDiscovery.mjs +1 -1
  16. package/dist/cache/CacheManager.mjs +46 -9
  17. package/dist/cache/CacheManager.mjs.map +1 -1
  18. package/dist/cache/persistence/TokenCacheContext.mjs +1 -1
  19. package/dist/cache/utils/AccountEntityUtils.mjs +1 -1
  20. package/dist/cache/utils/CacheHelpers.mjs +1 -1
  21. package/dist/client/AuthorizationCodeClient.mjs +5 -2
  22. package/dist/client/AuthorizationCodeClient.mjs.map +1 -1
  23. package/dist/client/RefreshTokenClient.mjs +1 -1
  24. package/dist/client/SilentFlowClient.mjs +1 -1
  25. package/dist/config/ClientConfiguration.mjs +1 -1
  26. package/dist/constants/AADServerParamKeys.mjs +9 -3
  27. package/dist/constants/AADServerParamKeys.mjs.map +1 -1
  28. package/dist/crypto/DpopProofGenerator.mjs +17 -7
  29. package/dist/crypto/DpopProofGenerator.mjs.map +1 -1
  30. package/dist/crypto/ICrypto.mjs +1 -1
  31. package/dist/crypto/ITokenBindingKeyManager.mjs +1 -1
  32. package/dist/crypto/ITokenBindingKeyManager.mjs.map +1 -1
  33. package/dist/crypto/JoseHeader.mjs +1 -1
  34. package/dist/crypto/PopTokenGenerator.mjs +1 -1
  35. package/dist/error/AuthError.mjs +1 -1
  36. package/dist/error/AuthErrorCodes.mjs +1 -1
  37. package/dist/error/CacheError.mjs +1 -1
  38. package/dist/error/CacheErrorCodes.mjs +1 -1
  39. package/dist/error/ClientAuthError.mjs +1 -1
  40. package/dist/error/ClientAuthErrorCodes.mjs +1 -1
  41. package/dist/error/ClientConfigurationError.mjs +1 -1
  42. package/dist/error/ClientConfigurationErrorCodes.mjs +1 -1
  43. package/dist/error/InteractionRequiredAuthError.mjs +1 -1
  44. package/dist/error/InteractionRequiredAuthErrorCodes.mjs +1 -1
  45. package/dist/error/JoseHeaderError.mjs +1 -1
  46. package/dist/error/JoseHeaderErrorCodes.mjs +1 -1
  47. package/dist/error/NetworkError.mjs +1 -1
  48. package/dist/error/PlatformBrokerError.mjs +1 -1
  49. package/dist/error/ServerError.mjs +1 -1
  50. package/dist/index-node.mjs +1 -1
  51. package/dist/index.mjs +2 -1
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/logger/Logger.mjs +1 -1
  54. package/dist/network/INetworkModule.mjs +1 -1
  55. package/dist/network/RequestThumbprint.mjs +1 -1
  56. package/dist/network/ResponseHeaders.mjs +43 -0
  57. package/dist/network/ResponseHeaders.mjs.map +1 -0
  58. package/dist/network/ThrottlingUtils.mjs +16 -11
  59. package/dist/network/ThrottlingUtils.mjs.map +1 -1
  60. package/dist/packageMetadata.mjs +2 -2
  61. package/dist/protocol/Authorize.mjs +5 -2
  62. package/dist/protocol/Authorize.mjs.map +1 -1
  63. package/dist/protocol/Token.mjs +9 -7
  64. package/dist/protocol/Token.mjs.map +1 -1
  65. package/dist/request/AuthenticationHeaderParser.mjs +6 -4
  66. package/dist/request/AuthenticationHeaderParser.mjs.map +1 -1
  67. package/dist/request/BaseAuthRequest.mjs +1 -1
  68. package/dist/request/RequestParameterBuilder.mjs +17 -3
  69. package/dist/request/RequestParameterBuilder.mjs.map +1 -1
  70. package/dist/request/ScopeSet.mjs +1 -1
  71. package/dist/response/ResponseHandler.mjs +1 -1
  72. package/dist/telemetry/performance/PerformanceClient.mjs +1 -1
  73. package/dist/telemetry/performance/PerformanceEvent.mjs +1 -1
  74. package/dist/telemetry/performance/PerformanceEvent.mjs.map +1 -1
  75. package/dist/telemetry/performance/PerformanceEvents.mjs +1 -1
  76. package/dist/telemetry/performance/StubPerformanceClient.mjs +1 -1
  77. package/dist/telemetry/server/ServerTelemetryManager.mjs +1 -1
  78. package/dist/url/UrlString.mjs +1 -1
  79. package/dist/utils/ClientAssertionUtils.mjs +1 -1
  80. package/dist/utils/Constants.mjs +1 -1
  81. package/dist/utils/FunctionWrappers.mjs +1 -1
  82. package/dist/utils/ObjectUtils.mjs +1 -1
  83. package/dist/utils/ProtocolUtils.mjs +1 -1
  84. package/dist/utils/StringUtils.mjs +1 -1
  85. package/dist/utils/TimeUtils.mjs +1 -1
  86. package/dist/utils/UrlUtils.mjs +12 -3
  87. package/dist/utils/UrlUtils.mjs.map +1 -1
  88. package/dist-browser/account/AccountInfo.mjs +1 -1
  89. package/dist-browser/account/AuthToken.mjs +1 -1
  90. package/dist-browser/account/CcsCredential.mjs +1 -1
  91. package/dist-browser/account/ClientInfo.mjs +1 -1
  92. package/dist-browser/account/TokenClaims.mjs +1 -1
  93. package/dist-browser/authority/Authority.mjs +1 -1
  94. package/dist-browser/authority/AuthorityFactory.mjs +1 -1
  95. package/dist-browser/authority/AuthorityMetadata.mjs +1 -1
  96. package/dist-browser/authority/AuthorityOptions.mjs +1 -1
  97. package/dist-browser/authority/AuthorityType.mjs +1 -1
  98. package/dist-browser/authority/CloudInstanceDiscoveryErrorResponse.mjs +1 -1
  99. package/dist-browser/authority/CloudInstanceDiscoveryResponse.mjs +1 -1
  100. package/dist-browser/authority/OpenIdConfigResponse.mjs +1 -1
  101. package/dist-browser/authority/ProtocolMode.mjs +1 -1
  102. package/dist-browser/authority/RegionDiscovery.mjs +1 -1
  103. package/dist-browser/cache/CacheManager.mjs +46 -9
  104. package/dist-browser/cache/CacheManager.mjs.map +1 -1
  105. package/dist-browser/cache/persistence/TokenCacheContext.mjs +1 -1
  106. package/dist-browser/cache/utils/AccountEntityUtils.mjs +1 -1
  107. package/dist-browser/cache/utils/CacheHelpers.mjs +1 -1
  108. package/dist-browser/client/AuthorizationCodeClient.mjs +5 -2
  109. package/dist-browser/client/AuthorizationCodeClient.mjs.map +1 -1
  110. package/dist-browser/client/RefreshTokenClient.mjs +1 -1
  111. package/dist-browser/client/SilentFlowClient.mjs +1 -1
  112. package/dist-browser/config/ClientConfiguration.mjs +1 -1
  113. package/dist-browser/constants/AADServerParamKeys.mjs +9 -3
  114. package/dist-browser/constants/AADServerParamKeys.mjs.map +1 -1
  115. package/dist-browser/crypto/DpopProofGenerator.mjs +17 -7
  116. package/dist-browser/crypto/DpopProofGenerator.mjs.map +1 -1
  117. package/dist-browser/crypto/ICrypto.mjs +1 -1
  118. package/dist-browser/crypto/ITokenBindingKeyManager.mjs +1 -1
  119. package/dist-browser/crypto/ITokenBindingKeyManager.mjs.map +1 -1
  120. package/dist-browser/crypto/JoseHeader.mjs +1 -1
  121. package/dist-browser/crypto/PopTokenGenerator.mjs +1 -1
  122. package/dist-browser/error/AuthError.mjs +1 -1
  123. package/dist-browser/error/AuthErrorCodes.mjs +1 -1
  124. package/dist-browser/error/CacheError.mjs +1 -1
  125. package/dist-browser/error/CacheErrorCodes.mjs +1 -1
  126. package/dist-browser/error/ClientAuthError.mjs +1 -1
  127. package/dist-browser/error/ClientAuthErrorCodes.mjs +1 -1
  128. package/dist-browser/error/ClientConfigurationError.mjs +1 -1
  129. package/dist-browser/error/ClientConfigurationErrorCodes.mjs +1 -1
  130. package/dist-browser/error/InteractionRequiredAuthError.mjs +1 -1
  131. package/dist-browser/error/InteractionRequiredAuthErrorCodes.mjs +1 -1
  132. package/dist-browser/error/JoseHeaderError.mjs +1 -1
  133. package/dist-browser/error/JoseHeaderErrorCodes.mjs +1 -1
  134. package/dist-browser/error/NetworkError.mjs +1 -1
  135. package/dist-browser/error/PlatformBrokerError.mjs +1 -1
  136. package/dist-browser/error/ServerError.mjs +1 -1
  137. package/dist-browser/index-browser.mjs +2 -1
  138. package/dist-browser/index-browser.mjs.map +1 -1
  139. package/dist-browser/index.mjs +2 -1
  140. package/dist-browser/index.mjs.map +1 -1
  141. package/dist-browser/log-strings-mapping.json +2 -2
  142. package/dist-browser/logger/Logger.mjs +1 -1
  143. package/dist-browser/network/INetworkModule.mjs +1 -1
  144. package/dist-browser/network/RequestThumbprint.mjs +1 -1
  145. package/dist-browser/network/ResponseHeaders.mjs +43 -0
  146. package/dist-browser/network/ResponseHeaders.mjs.map +1 -0
  147. package/dist-browser/network/ThrottlingUtils.mjs +16 -11
  148. package/dist-browser/network/ThrottlingUtils.mjs.map +1 -1
  149. package/dist-browser/packageMetadata.mjs +2 -2
  150. package/dist-browser/protocol/Authorize.mjs +5 -2
  151. package/dist-browser/protocol/Authorize.mjs.map +1 -1
  152. package/dist-browser/protocol/Token.mjs +9 -7
  153. package/dist-browser/protocol/Token.mjs.map +1 -1
  154. package/dist-browser/request/AuthenticationHeaderParser.mjs +6 -4
  155. package/dist-browser/request/AuthenticationHeaderParser.mjs.map +1 -1
  156. package/dist-browser/request/BaseAuthRequest.mjs +1 -1
  157. package/dist-browser/request/RequestParameterBuilder.mjs +17 -3
  158. package/dist-browser/request/RequestParameterBuilder.mjs.map +1 -1
  159. package/dist-browser/request/ScopeSet.mjs +1 -1
  160. package/dist-browser/response/ResponseHandler.mjs +1 -1
  161. package/dist-browser/telemetry/performance/PerformanceClient.mjs +1 -1
  162. package/dist-browser/telemetry/performance/PerformanceEvent.mjs +1 -1
  163. package/dist-browser/telemetry/performance/PerformanceEvent.mjs.map +1 -1
  164. package/dist-browser/telemetry/performance/PerformanceEvents.mjs +1 -1
  165. package/dist-browser/telemetry/performance/StubPerformanceClient.mjs +1 -1
  166. package/dist-browser/telemetry/server/ServerTelemetryManager.mjs +1 -1
  167. package/dist-browser/url/UrlString.mjs +1 -1
  168. package/dist-browser/utils/ClientAssertionUtils.mjs +1 -1
  169. package/dist-browser/utils/Constants.mjs +1 -1
  170. package/dist-browser/utils/FunctionWrappers.mjs +1 -1
  171. package/dist-browser/utils/ObjectUtils.mjs +1 -1
  172. package/dist-browser/utils/ProtocolUtils.mjs +1 -1
  173. package/dist-browser/utils/StringUtils.mjs +1 -1
  174. package/dist-browser/utils/TimeUtils.mjs +1 -1
  175. package/dist-browser/utils/UrlUtils.mjs +12 -3
  176. package/dist-browser/utils/UrlUtils.mjs.map +1 -1
  177. package/lib/index-browser.cjs +4 -2
  178. package/lib/index-browser.cjs.map +1 -1
  179. package/lib/{index-node-cgWrVUUm.js → index-node-C1QI6fAD.js} +168 -37
  180. package/lib/index-node-C1QI6fAD.js.map +1 -0
  181. package/lib/index-node.cjs +2 -2
  182. package/lib/index.cjs +4 -2
  183. package/lib/index.cjs.map +1 -1
  184. package/package.json +1 -1
  185. package/src/cache/CacheManager.ts +87 -15
  186. package/src/client/AuthorizationCodeClient.ts +4 -0
  187. package/src/constants/AADServerParamKeys.ts +6 -0
  188. package/src/crypto/DpopProofGenerator.ts +36 -5
  189. package/src/crypto/ITokenBindingKeyManager.ts +11 -0
  190. package/src/exports-browser-only.ts +5 -0
  191. package/src/network/NetworkResponse.ts +3 -0
  192. package/src/network/ResponseHeaders.ts +52 -0
  193. package/src/network/ThrottlingUtils.ts +20 -15
  194. package/src/packageMetadata.ts +1 -1
  195. package/src/protocol/Authorize.ts +4 -0
  196. package/src/protocol/Token.ts +19 -6
  197. package/src/request/AuthenticationHeaderParser.ts +14 -3
  198. package/src/request/CommonAuthorizationUrlRequest.ts +8 -0
  199. package/src/request/CommonEndSessionRequest.ts +8 -0
  200. package/src/request/RequestParameterBuilder.ts +15 -0
  201. package/src/telemetry/performance/PerformanceEvent.ts +12 -0
  202. package/src/utils/UrlUtils.ts +12 -2
  203. package/types/cache/CacheManager.d.ts +9 -0
  204. package/types/cache/CacheManager.d.ts.map +1 -1
  205. package/types/client/AuthorizationCodeClient.d.ts.map +1 -1
  206. package/types/constants/AADServerParamKeys.d.ts +6 -0
  207. package/types/constants/AADServerParamKeys.d.ts.map +1 -1
  208. package/types/crypto/DpopProofGenerator.d.ts +20 -3
  209. package/types/crypto/DpopProofGenerator.d.ts.map +1 -1
  210. package/types/crypto/ITokenBindingKeyManager.d.ts +8 -0
  211. package/types/crypto/ITokenBindingKeyManager.d.ts.map +1 -1
  212. package/types/exports-browser-only.d.ts +2 -0
  213. package/types/exports-browser-only.d.ts.map +1 -1
  214. package/types/network/NetworkResponse.d.ts +3 -0
  215. package/types/network/NetworkResponse.d.ts.map +1 -1
  216. package/types/network/ResponseHeaders.d.ts +13 -0
  217. package/types/network/ResponseHeaders.d.ts.map +1 -0
  218. package/types/network/ThrottlingUtils.d.ts +2 -2
  219. package/types/network/ThrottlingUtils.d.ts.map +1 -1
  220. package/types/packageMetadata.d.ts +1 -1
  221. package/types/protocol/Authorize.d.ts.map +1 -1
  222. package/types/protocol/Token.d.ts.map +1 -1
  223. package/types/request/AuthenticationHeaderParser.d.ts +1 -0
  224. package/types/request/AuthenticationHeaderParser.d.ts.map +1 -1
  225. package/types/request/CommonAuthorizationUrlRequest.d.ts +8 -0
  226. package/types/request/CommonAuthorizationUrlRequest.d.ts.map +1 -1
  227. package/types/request/CommonEndSessionRequest.d.ts +8 -0
  228. package/types/request/CommonEndSessionRequest.d.ts.map +1 -1
  229. package/types/request/RequestParameterBuilder.d.ts +10 -0
  230. package/types/request/RequestParameterBuilder.d.ts.map +1 -1
  231. package/types/telemetry/performance/PerformanceEvent.d.ts +10 -0
  232. package/types/telemetry/performance/PerformanceEvent.d.ts.map +1 -1
  233. package/types/utils/UrlUtils.d.ts +2 -1
  234. package/types/utils/UrlUtils.d.ts.map +1 -1
  235. package/lib/index-node-cgWrVUUm.js.map +0 -1
package/lib/index.cjs CHANGED
@@ -1,8 +1,8 @@
1
- /*! @azure/msal-common v16.14.3 2026-10-21 */
1
+ /*! @azure/msal-common v16.16.0 2026-11-05 */
2
2
  'use strict';
3
3
  'use strict';
4
4
 
5
- var indexNode = require('./index-node-cgWrVUUm.js');
5
+ var indexNode = require('./index-node-C1QI6fAD.js');
6
6
  var indexBrowser = require('./index-browser.cjs');
7
7
 
8
8
 
@@ -34,6 +34,7 @@ exports.DEFAULT_CRYPTO_IMPLEMENTATION = indexNode.DEFAULT_CRYPTO_IMPLEMENTATION;
34
34
  exports.DEFAULT_SYSTEM_OPTIONS = indexNode.DEFAULT_SYSTEM_OPTIONS;
35
35
  exports.DEFAULT_TOKEN_BINDING_KEY_MANAGER = indexNode.DEFAULT_TOKEN_BINDING_KEY_MANAGER;
36
36
  exports.DefaultStorageClass = indexNode.DefaultStorageClass;
37
+ exports.DpopProofGenerator = indexNode.DpopProofGenerator;
37
38
  exports.IntFields = indexNode.IntFields;
38
39
  exports.InteractionRequiredAuthError = indexNode.InteractionRequiredAuthError;
39
40
  exports.InteractionRequiredAuthErrorCodes = indexNode.InteractionRequiredAuthErrorCodes;
@@ -87,6 +88,7 @@ exports.getRequestThumbprint = indexNode.getRequestThumbprint;
87
88
  exports.getTenantIdFromIdTokenClaims = indexNode.getTenantIdFromIdTokenClaims;
88
89
  exports.invoke = indexNode.invoke;
89
90
  exports.invokeAsync = indexNode.invokeAsync;
91
+ exports.normalizeDpopResourceRequestContext = indexNode.normalizeDpopResourceRequestContext;
90
92
  exports.tenantIdMatchesHomeTenant = indexNode.tenantIdMatchesHomeTenant;
91
93
  exports.updateAccountTenantProfileData = indexNode.updateAccountTenantProfileData;
92
94
  exports.version = indexNode.version;
package/lib/index.cjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -10,7 +10,7 @@
10
10
  "type": "git",
11
11
  "url": "https://github.com/AzureAD/microsoft-authentication-library-for-js.git"
12
12
  },
13
- "version": "16.14.3",
13
+ "version": "16.16.0",
14
14
  "description": "Microsoft Authentication Library for js",
15
15
  "keywords": [
16
16
  "implicit",
@@ -719,6 +719,7 @@ export abstract class CacheManager implements ICacheManager {
719
719
  correlationId
720
720
  );
721
721
 
722
+ const accessTokenKeysToRemove: string[] = [];
722
723
  tokenKeys.accessToken.forEach((key) => {
723
724
  if (
724
725
  !this.accessTokenKeyMatchesFilter(key, accessTokenFilter, false)
@@ -744,10 +745,17 @@ export abstract class CacheManager implements ICacheManager {
744
745
  correlationId
745
746
  );
746
747
  if (tokenScopeSet.intersectingScopeSets(currentScopes)) {
747
- this.removeAccessToken(key, correlationId);
748
+ accessTokenKeysToRemove.push(key);
748
749
  }
749
750
  }
750
751
  });
752
+ for (const key of accessTokenKeysToRemove) {
753
+ await this.removeAccessTokenAndTokenBindingKey(
754
+ key,
755
+ correlationId,
756
+ credential.keyId
757
+ );
758
+ }
751
759
  await this.setAccessTokenCredential(
752
760
  credential,
753
761
  correlationId,
@@ -1100,9 +1108,42 @@ export abstract class CacheManager implements ICacheManager {
1100
1108
  * @param correlationId
1101
1109
  */
1102
1110
  removeAccessToken(key: string, correlationId: string): void {
1111
+ const credential = this.removeAccessTokenCredential(key, correlationId);
1112
+ if (credential) {
1113
+ void this.removeTokenBindingKeyForCredential(
1114
+ credential,
1115
+ correlationId
1116
+ );
1117
+ }
1118
+ }
1119
+
1120
+ /**
1121
+ * Removes an access token and waits for any unreferenced token-binding key
1122
+ * cleanup. Internal callers that require deterministic cleanup should use
1123
+ * this method instead of the synchronous public cache contract.
1124
+ */
1125
+ async removeAccessTokenAndTokenBindingKey(
1126
+ key: string,
1127
+ correlationId: string,
1128
+ preservedKeyId?: string
1129
+ ): Promise<void> {
1130
+ const credential = this.removeAccessTokenCredential(key, correlationId);
1131
+ if (credential) {
1132
+ await this.removeTokenBindingKeyForCredential(
1133
+ credential,
1134
+ correlationId,
1135
+ preservedKeyId
1136
+ );
1137
+ }
1138
+ }
1139
+
1140
+ private removeAccessTokenCredential(
1141
+ key: string,
1142
+ correlationId: string
1143
+ ): AccessTokenEntity | null {
1103
1144
  const credential = this.getAccessTokenCredential(key, correlationId);
1104
1145
  if (!credential) {
1105
- return;
1146
+ return null;
1106
1147
  }
1107
1148
 
1108
1149
  this.removeItem(key, correlationId);
@@ -1110,7 +1151,14 @@ export abstract class CacheManager implements ICacheManager {
1110
1151
  { accessTokensRemoved: 1 },
1111
1152
  correlationId
1112
1153
  );
1154
+ return credential;
1155
+ }
1113
1156
 
1157
+ private async removeTokenBindingKeyForCredential(
1158
+ credential: AccessTokenEntity,
1159
+ correlationId: string,
1160
+ preservedKeyId?: string
1161
+ ): Promise<void> {
1114
1162
  // Remove Token Binding Key from key store for token-bound access token credentials
1115
1163
  if (
1116
1164
  credential.credentialType.toLowerCase() ===
@@ -1124,19 +1172,26 @@ export abstract class CacheManager implements ICacheManager {
1124
1172
  credential as AccessTokenEntity;
1125
1173
  const kid = accessTokenWithAuthSchemeEntity.keyId;
1126
1174
 
1127
- if (kid) {
1128
- void this.tokenBindingKeyManager
1129
- .removeTokenBindingKey(kid, correlationId)
1130
- .catch(() => {
1131
- this.commonLogger.error(
1132
- "Failed to remove token binding key",
1133
- correlationId
1134
- );
1135
- this.performanceClient?.incrementFields(
1136
- { removeTokenBindingKeyFailure: 1 },
1137
- correlationId
1138
- );
1139
- });
1175
+ if (
1176
+ kid &&
1177
+ kid !== preservedKeyId &&
1178
+ !this.isTokenBindingKeyReferenced(kid, correlationId)
1179
+ ) {
1180
+ try {
1181
+ await this.tokenBindingKeyManager.removeTokenBindingKey(
1182
+ kid,
1183
+ correlationId
1184
+ );
1185
+ } catch {
1186
+ this.commonLogger.error(
1187
+ "Failed to remove token binding key",
1188
+ correlationId
1189
+ );
1190
+ this.performanceClient?.incrementFields(
1191
+ { removeTokenBindingKeyFailure: 1 },
1192
+ correlationId
1193
+ );
1194
+ }
1140
1195
  }
1141
1196
  break;
1142
1197
  }
@@ -1144,6 +1199,19 @@ export abstract class CacheManager implements ICacheManager {
1144
1199
  }
1145
1200
  }
1146
1201
 
1202
+ private isTokenBindingKeyReferenced(
1203
+ keyId: string,
1204
+ correlationId: string
1205
+ ): boolean {
1206
+ return this.getTokenKeys().accessToken.some((accessTokenKey) => {
1207
+ const accessToken = this.getAccessTokenCredential(
1208
+ accessTokenKey,
1209
+ correlationId
1210
+ );
1211
+ return accessToken?.keyId === keyId;
1212
+ });
1213
+ }
1214
+
1147
1215
  /**
1148
1216
  * Removes all app metadata objects from cache.
1149
1217
  */
@@ -1358,6 +1426,7 @@ export abstract class CacheManager implements ICacheManager {
1358
1426
  const authScheme =
1359
1427
  request.authenticationScheme ||
1360
1428
  Constants.AuthenticationScheme.BEARER;
1429
+ const normalizedAuthScheme = authScheme.toLowerCase();
1361
1430
  /*
1362
1431
  * Distinguish between Bearer and PoP/SSH token cache types
1363
1432
  * Cast to lowercase to handle "bearer" from ADFS
@@ -1388,6 +1457,9 @@ export abstract class CacheManager implements ICacheManager {
1388
1457
  keyId:
1389
1458
  authScheme === Constants.AuthenticationScheme.SSH
1390
1459
  ? request.sshKid
1460
+ : normalizedAuthScheme ===
1461
+ Constants.AuthenticationScheme.DPOP.toLowerCase()
1462
+ ? request.popKid || request.dpopJkt
1391
1463
  : undefined,
1392
1464
  additionalCacheKeyComponents: additionalCacheKeyComponents,
1393
1465
  };
@@ -597,6 +597,10 @@ export class AuthorizationCodeClient {
597
597
  );
598
598
  }
599
599
 
600
+ if (request.popupOriginCheckDone) {
601
+ RequestParameterBuilder.addPopupOriginCheckDone(parameters);
602
+ }
603
+
600
604
  if (request.extraQueryParameters) {
601
605
  RequestParameterBuilder.addExtraParameters(
602
606
  parameters,
@@ -70,3 +70,9 @@ export const USERNAME = "username";
70
70
  export const USER_ID = "user_id";
71
71
  export const FMI_PATH = "fmi_path";
72
72
  export const ATTRIBUTE_TOKENS = "attribute_tokens";
73
+ /**
74
+ * Popup-origin-check-done. Signals to the STS that the client verified the
75
+ * popup cannot be reached by an untrusted window, so the
76
+ * Cross-Origin-Opener-Policy response header may be omitted.
77
+ */
78
+ export const POPUP_ORIGIN_CHECK_DONE = "pocd";
@@ -47,6 +47,20 @@ export type DpopResourceProofParams = {
47
47
  nonce?: string;
48
48
  };
49
49
 
50
+ /**
51
+ * HTTP resource context used by a DPoP-bound request.
52
+ * @internal
53
+ */
54
+ export type DpopResourceRequestContext = {
55
+ htu: string;
56
+ htm: string;
57
+ };
58
+
59
+ /**
60
+ * Resource request context and access token used to generate a DPoP proof.
61
+ * Exported for use by MSAL Browser and unsupported for direct consumers.
62
+ * @internal
63
+ */
50
64
  export type GenerateDpopResourceProofParams = {
51
65
  htu?: string;
52
66
  htm?: string;
@@ -128,13 +142,26 @@ function validateDpopNonce(
128
142
  }
129
143
  }
130
144
 
145
+ /**
146
+ * Validates and normalizes the HTTP resource context for a DPoP-bound request.
147
+ * @internal
148
+ */
149
+ export function normalizeDpopResourceRequestContext(
150
+ context: DpopResourceRequestContext,
151
+ correlationId: string = ""
152
+ ): DpopResourceRequestContext {
153
+ return {
154
+ htm: normalizeHtm(context.htm, correlationId),
155
+ htu: normalizeHtu(context.htu, correlationId),
156
+ };
157
+ }
158
+
131
159
  /**
132
160
  * Builds RFC 9449 DPoP proof JWT payloads for token-endpoint and
133
161
  * resource-endpoint proof bindings.
134
162
  *
135
- * Not exported from any public package entry point.
136
- * This helper is internal-only until DPoP is wired into acquisition flows
137
- * in a subsequent work item.
163
+ * Exported from package entry points for use by MSAL Browser.
164
+ * This helper remains an unsupported internal API for direct consumers.
138
165
  *
139
166
  * DPoP proofs do not contain SHR fields (at, ts, m, u, p, q).
140
167
  * @internal
@@ -213,10 +240,14 @@ export class DpopProofGenerator {
213
240
  correlationId: string = ""
214
241
  ): DpopProofClaims {
215
242
  validateDpopNonce(params.nonce, correlationId);
243
+ const resourceContext = normalizeDpopResourceRequestContext(
244
+ params,
245
+ correlationId
246
+ );
216
247
  const claims: DpopProofClaims = {
217
248
  jti: this.cryptoUtils.createNewGuid(),
218
- htm: normalizeHtm(params.htm, correlationId),
219
- htu: normalizeHtu(params.htu, correlationId),
249
+ htm: resourceContext.htm,
250
+ htu: resourceContext.htu,
220
251
  ath: params.ath,
221
252
  iat: TimeUtils.nowSeconds(),
222
253
  };
@@ -39,6 +39,17 @@ export interface ITokenBindingKeyManager {
39
39
  * @param correlationId - Request correlation identifier.
40
40
  */
41
41
  removeTokenBindingKey(kid: string, correlationId: string): Promise<void>;
42
+ /**
43
+ * Returns whether a token-binding key is available to the current context.
44
+ */
45
+ hasTokenBindingKey?(kid: string, correlationId: string): Promise<boolean>;
46
+ /**
47
+ * Returns whether a token-binding key is available in persistent storage.
48
+ */
49
+ isTokenBindingKeyPersisted?(
50
+ kid: string,
51
+ correlationId: string
52
+ ): Promise<boolean>;
42
53
  /**
43
54
  * Gets a token-binding public key as a JWK by identifier.
44
55
  * @param kid - Token-binding key identifier.
@@ -23,3 +23,8 @@ export { PerformanceClient } from "./telemetry/performance/PerformanceClient.js"
23
23
  export { StubPerformanceClient } from "./telemetry/performance/StubPerformanceClient.js";
24
24
 
25
25
  export { PopTokenGenerator } from "./crypto/PopTokenGenerator.js";
26
+ export {
27
+ DpopProofGenerator,
28
+ normalizeDpopResourceRequestContext,
29
+ } from "./crypto/DpopProofGenerator.js";
30
+ export type { DpopResourceRequestContext } from "./crypto/DpopProofGenerator.js";
@@ -4,6 +4,9 @@
4
4
  */
5
5
 
6
6
  export type NetworkResponse<T> = {
7
+ /**
8
+ * Header names are case-insensitive. Built-in clients return lowercase keys.
9
+ */
7
10
  headers: Record<string, string>;
8
11
  body: T;
9
12
  status: number;
@@ -0,0 +1,52 @@
1
+ /*
2
+ * Copyright (c) Microsoft Corporation. All rights reserved.
3
+ * Licensed under the MIT License.
4
+ */
5
+
6
+ // Track only our normalized copies, never caller-owned mutable inputs.
7
+ const normalizedHeaderRecords = new WeakSet<Record<string, string>>();
8
+
9
+ /**
10
+ * Creates a lowercase-keyed snapshot without changing header values or the input.
11
+ * Reuses snapshots produced by this function to avoid repeated normalization.
12
+ * @internal
13
+ */
14
+ export function normalizeResponseHeaders(
15
+ headers: Record<string, string>
16
+ ): Record<string, string> {
17
+ if (normalizedHeaderRecords.has(headers)) {
18
+ return headers;
19
+ }
20
+
21
+ const normalized = Object.fromEntries<string>(
22
+ Object.entries(headers).map(([name, value]): [string, string] => [
23
+ name.toLowerCase(),
24
+ value,
25
+ ])
26
+ );
27
+ normalizedHeaderRecords.add(normalized);
28
+ return normalized;
29
+ }
30
+
31
+ /**
32
+ * Reads a response header case-insensitively.
33
+ * Normalized snapshots are never scanned, even when a header is missing.
34
+ * @internal
35
+ */
36
+ export function getResponseHeader(
37
+ headers: Record<string, string>,
38
+ name: string
39
+ ): string | undefined {
40
+ const key = name.toLowerCase();
41
+ if (Object.prototype.hasOwnProperty.call(headers, key)) {
42
+ return headers[key];
43
+ }
44
+ if (normalizedHeaderRecords.has(headers)) {
45
+ return undefined;
46
+ }
47
+
48
+ const headerName = Object.keys(headers).find(
49
+ (header) => header.toLowerCase() === key
50
+ );
51
+ return headerName === undefined ? undefined : headers[headerName];
52
+ }
@@ -14,6 +14,7 @@ import {
14
14
  } from "./RequestThumbprint.js";
15
15
  import { ThrottlingEntity } from "../cache/entities/ThrottlingEntity.js";
16
16
  import { BaseAuthRequest } from "../request/BaseAuthRequest.js";
17
+ import { getResponseHeader } from "./ResponseHeaders.js";
17
18
 
18
19
  /** @internal */
19
20
  export class ThrottlingUtils {
@@ -56,7 +57,7 @@ export class ThrottlingUtils {
56
57
  * Performs necessary throttling checks after a network request.
57
58
  * @param cacheManager
58
59
  * @param thumbprint
59
- * @param response
60
+ * @param response - Token response with case-insensitive header names.
60
61
  */
61
62
  static postProcess(
62
63
  cacheManager: CacheManager,
@@ -64,15 +65,14 @@ export class ThrottlingUtils {
64
65
  response: NetworkResponse<ServerAuthorizationTokenResponse>,
65
66
  correlationId: string
66
67
  ): void {
68
+ const retryAfter = getRetryAfterHeader(response);
67
69
  if (
68
70
  ThrottlingUtils.checkResponseStatus(response) ||
69
- ThrottlingUtils.checkResponseForRetryAfter(response)
71
+ retryAfter !== undefined
70
72
  ) {
71
73
  const thumbprintValue: ThrottlingEntity = {
72
74
  throttleTime: ThrottlingUtils.calculateThrottleTime(
73
- parseInt(
74
- response.headers[Constants.HeaderNames.RETRY_AFTER]
75
- )
75
+ parseInt(retryAfter || "")
76
76
  ),
77
77
  error: response.body.error,
78
78
  errorCodes: response.body.error_codes,
@@ -102,20 +102,12 @@ export class ThrottlingUtils {
102
102
 
103
103
  /**
104
104
  * Checks a NetworkResponse object's RetryAfter header
105
- * @param response
105
+ * @param response - Token response with case-insensitive header names.
106
106
  */
107
107
  static checkResponseForRetryAfter(
108
108
  response: NetworkResponse<ServerAuthorizationTokenResponse>
109
109
  ): boolean {
110
- if (response.headers) {
111
- return (
112
- response.headers.hasOwnProperty(
113
- Constants.HeaderNames.RETRY_AFTER
114
- ) &&
115
- (response.status < 200 || response.status >= 300)
116
- );
117
- }
118
- return false;
110
+ return getRetryAfterHeader(response) !== undefined;
119
111
  }
120
112
 
121
113
  /**
@@ -150,3 +142,16 @@ export class ThrottlingUtils {
150
142
  cacheManager.removeItem(key, request.correlationId);
151
143
  }
152
144
  }
145
+
146
+ /** Reads Retry-After only for non-success responses. */
147
+ function getRetryAfterHeader(
148
+ response: NetworkResponse<ServerAuthorizationTokenResponse>
149
+ ): string | undefined {
150
+ if ((response.status < 200 || response.status >= 300) && response.headers) {
151
+ return getResponseHeader(
152
+ response.headers,
153
+ Constants.HeaderNames.RETRY_AFTER
154
+ );
155
+ }
156
+ return undefined;
157
+ }
@@ -1,3 +1,3 @@
1
1
  /* eslint-disable header/header */
2
2
  export const name = "@azure/msal-common";
3
- export const version = "16.14.3";
3
+ export const version = "16.16.0";
@@ -267,6 +267,10 @@ export function getStandardAuthorizeRequestParameters(
267
267
  RequestParameterBuilder.addInstanceAware(parameters);
268
268
  }
269
269
 
270
+ if (request.popupOriginCheckDone) {
271
+ RequestParameterBuilder.addPopupOriginCheckDone(parameters);
272
+ }
273
+
270
274
  return parameters;
271
275
  }
272
276
 
@@ -23,6 +23,10 @@ import {
23
23
  NetworkRequestOptions,
24
24
  } from "../network/INetworkModule.js";
25
25
  import { NetworkResponse } from "../network/NetworkResponse.js";
26
+ import {
27
+ getResponseHeader,
28
+ normalizeResponseHeaders,
29
+ } from "../network/ResponseHeaders.js";
26
30
  import { ThrottlingUtils } from "../network/ThrottlingUtils.js";
27
31
  import { NetworkError } from "../error/NetworkError.js";
28
32
  import { AuthError } from "../error/AuthError.js";
@@ -223,7 +227,10 @@ export async function sendPostRequest<
223
227
  performanceClient,
224
228
  correlationId
225
229
  )(tokenEndpoint, { ...options, correlationId, performanceClient });
226
- const responseHeaders = response.headers || {};
230
+ const responseHeaders = normalizeResponseHeaders(
231
+ response.headers || {}
232
+ );
233
+ response = { ...response, headers: responseHeaders };
227
234
  performanceClient?.addFields(
228
235
  {
229
236
  refreshTokenSize: response.body.refresh_token?.length || 0,
@@ -235,7 +242,9 @@ export async function sendPostRequest<
235
242
  );
236
243
  } catch (e) {
237
244
  if (e instanceof NetworkError) {
238
- const responseHeaders = e.responseHeaders;
245
+ const responseHeaders = e.responseHeaders
246
+ ? normalizeResponseHeaders(e.responseHeaders)
247
+ : undefined;
239
248
  if (responseHeaders) {
240
249
  performanceClient?.addFields(
241
250
  {
@@ -245,11 +254,15 @@ export async function sendPostRequest<
245
254
  requestId:
246
255
  responseHeaders[HeaderNames.X_MS_REQUEST_ID] || "",
247
256
  contentTypeHeader:
248
- responseHeaders[HeaderNames.CONTENT_TYPE] ||
249
- undefined,
257
+ getResponseHeader(
258
+ responseHeaders,
259
+ HeaderNames.CONTENT_TYPE
260
+ ) || undefined,
250
261
  contentLengthHeader:
251
- responseHeaders[HeaderNames.CONTENT_LENGTH] ||
252
- undefined,
262
+ getResponseHeader(
263
+ responseHeaders,
264
+ HeaderNames.CONTENT_LENGTH
265
+ ) || undefined,
253
266
  httpStatus: e.httpStatus,
254
267
  },
255
268
  correlationId
@@ -8,6 +8,10 @@ import {
8
8
  ClientConfigurationErrorCodes,
9
9
  } from "../error/ClientConfigurationError.js";
10
10
  import { HeaderNames } from "../utils/Constants.js";
11
+ import {
12
+ getResponseHeader,
13
+ normalizeResponseHeaders,
14
+ } from "../network/ResponseHeaders.js";
11
15
 
12
16
  type WWWAuthenticateChallenges = {
13
17
  nonce?: string;
@@ -24,8 +28,9 @@ type AuthenticationInfoChallenges = {
24
28
  export class AuthenticationHeaderParser {
25
29
  private headers: Record<string, string>;
26
30
 
31
+ /** Captures a case-insensitive snapshot of the response headers. */
27
32
  constructor(headers: Record<string, string>) {
28
- this.headers = headers;
33
+ this.headers = normalizeResponseHeaders(headers);
29
34
  }
30
35
 
31
36
  /**
@@ -34,7 +39,10 @@ export class AuthenticationHeaderParser {
34
39
  */
35
40
  getShrNonce(): string {
36
41
  // Attempt to parse nonce from Authentiacation-Info
37
- const authenticationInfo = this.headers[HeaderNames.AuthenticationInfo];
42
+ const authenticationInfo = getResponseHeader(
43
+ this.headers,
44
+ HeaderNames.AuthenticationInfo
45
+ );
38
46
  if (authenticationInfo) {
39
47
  const authenticationInfoChallenges =
40
48
  this.parseChallenges<AuthenticationInfoChallenges>(
@@ -50,7 +58,10 @@ export class AuthenticationHeaderParser {
50
58
  }
51
59
 
52
60
  // Attempt to parse nonce from WWW-Authenticate
53
- const wwwAuthenticate = this.headers[HeaderNames.WWWAuthenticate];
61
+ const wwwAuthenticate = getResponseHeader(
62
+ this.headers,
63
+ HeaderNames.WWWAuthenticate
64
+ );
54
65
  if (wwwAuthenticate) {
55
66
  const wwwAuthenticateChallenges =
56
67
  this.parseChallenges<WWWAuthenticateChallenges>(
@@ -78,4 +78,12 @@ export type CommonAuthorizationUrlRequest = BaseAuthRequest & {
78
78
  * @internal
79
79
  */
80
80
  reqCnf?: string;
81
+ /**
82
+ * Adds `pocd=1`, signalling that no untrusted window can reach the window
83
+ * driving this request. msal-browser computes this for every authorize
84
+ * request; a flow sets it explicitly only to assert a value the current
85
+ * window cannot be measured for, such as the popup-relay topology.
86
+ * @internal
87
+ */
88
+ popupOriginCheckDone?: boolean;
81
89
  };
@@ -38,4 +38,12 @@ export type CommonEndSessionRequest = {
38
38
  * String to string map of custom query parameters added to the /authorize call
39
39
  */
40
40
  extraQueryParameters?: StringDict;
41
+ /**
42
+ * Adds `pocd=1`, signalling that no untrusted window can reach the window
43
+ * driving this request. msal-browser computes this for every end-session
44
+ * request; a flow sets it explicitly only to assert a value the current
45
+ * window cannot be measured for, such as the popup-relay topology.
46
+ * @internal
47
+ */
48
+ popupOriginCheckDone?: boolean;
41
49
  };
@@ -474,6 +474,21 @@ export function addInstanceAware(parameters: Map<string, string>): void {
474
474
  }
475
475
  }
476
476
 
477
+ /**
478
+ * Adds `pocd=1`, telling the STS that the client verified the popup driving
479
+ * this request cannot be reached by an untrusted window, so the
480
+ * Cross-Origin-Opener-Policy response header may be omitted.
481
+ *
482
+ * Only ever added when the check passed — a negative result is signalled by
483
+ * omitting the parameter, which keeps the STS default (apply COOP) and stays
484
+ * compatible with library versions that never send it.
485
+ */
486
+ export function addPopupOriginCheckDone(parameters: Map<string, string>): void {
487
+ if (!parameters.has(AADServerParamKeys.POPUP_ORIGIN_CHECK_DONE)) {
488
+ parameters.set(AADServerParamKeys.POPUP_ORIGIN_CHECK_DONE, "1");
489
+ }
490
+ }
491
+
477
492
  /**
478
493
  * Add extraParameters
479
494
  * @param extraParams - String dictionary containing extra parameters to be added.
@@ -372,6 +372,18 @@ export type PerformanceEvent = {
372
372
 
373
373
  isAsyncPopup?: boolean;
374
374
 
375
+ /**
376
+ * Whether the auth response was collected via the legacy (non-COOP)
377
+ * location-polling flow rather than the BroadcastChannel redirect bridge.
378
+ */
379
+ usesLegacyPolling?: boolean;
380
+
381
+ /**
382
+ * Timeout, in milliseconds, applied while polling a silent iframe for the
383
+ * auth response under the legacy polling flow.
384
+ */
385
+ iframePollTimeout?: number;
386
+
375
387
  cacheRtExpiresOnSeconds?: number;
376
388
  ntwkRtExpiresOnSeconds?: number;
377
389
  extRtExpiresOnSeconds?: number;