Skip to content

Commit 0f8e2e1

Browse files
committed
Make extra cache key hash more generic
1 parent deba5cb commit 0f8e2e1

3 files changed

Lines changed: 50 additions & 20 deletions

File tree

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AcquireTokenByClientCredentialSupplier.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@ AuthenticationResult execute() throws Exception {
4040
context,
4141
null);
4242

43-
// Propagate ext_cache_key_hash for fmi_path-based cache isolation
44-
String extCacheKeyHash = this.clientCredentialRequest.parameters.computeFmiCacheKeyHash();
43+
// Propagate ext_cache_key_hash for cache isolation (e.g., fmi_path, credential_fmi_path)
44+
String extCacheKeyHash = this.clientCredentialRequest.parameters.computeExtCacheKeyHash();
4545
if (!StringHelper.isBlank(extCacheKeyHash)) {
4646
silentRequest.extCacheKeyHash(extCacheKeyHash);
4747
}

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ClientCredentialParameters.java

Lines changed: 46 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import java.util.Map;
77
import java.util.Set;
8+
import java.util.SortedMap;
89
import java.util.TreeMap;
910

1011
import static com.microsoft.aad.msal4j.ParameterValidationUtils.validateNotNull;
@@ -31,6 +32,15 @@ public class ClientCredentialParameters implements IAcquireTokenParameters {
3132

3233
private String fmiPath;
3334

35+
// Generic extended cache key components. Any parameter that should influence token cache
36+
// isolation adds an entry here (e.g., fmi_path, credential_fmi_path). The hash of these
37+
// components is used as part of the cache key for AccessToken_Extended entries.
38+
// Matches MSAL .NET's AdditionalCacheKeyComponents / CacheKeyComponents pattern.
39+
private SortedMap<String, String> cacheKeyComponents;
40+
41+
// Memoized hash of cacheKeyComponents (computed once since parameters are immutable).
42+
private String extCacheKeyHashCache;
43+
3444
private ClientCredentialParameters(Set<String> scopes, Boolean skipCache, ClaimsRequest claims, Map<String, String> extraHttpHeaders, Map<String, String> extraQueryParameters, String tenant, IClientCredential clientCredential, String fmiPath) {
3545
this.scopes = scopes;
3646
this.skipCache = skipCache;
@@ -40,6 +50,9 @@ private ClientCredentialParameters(Set<String> scopes, Boolean skipCache, Claims
4050
this.tenant = tenant;
4151
this.clientCredential = clientCredential;
4252
this.fmiPath = fmiPath;
53+
54+
// Build cache key components from any parameters that require cache isolation.
55+
this.cacheKeyComponents = buildCacheKeyComponents();
4356
}
4457

4558
private static ClientCredentialParametersBuilder builder() {
@@ -103,26 +116,43 @@ public String fmiPath() {
103116
}
104117

105118
/**
106-
* Computes the extended cache key hash for this request's fmi_path, if set.
107-
* Returns an empty string if fmiPath is not set.
108-
* This is the single source of truth for the fmi_path cache key hash computation,
109-
* used by both cache writes (TokenCache) and cache reads (silent lookup).
110-
* The result is memoized since ClientCredentialParameters is immutable after construction.
119+
* Builds the sorted map of cache key components from the parameters that require
120+
* cache isolation. Returns null if no components are present.
121+
* <p>
122+
* This is the single place where parameters contribute to the extended cache key.
123+
* To add a new cache key component, add an entry here — the hash computation and
124+
* cache read/write logic are fully generic and require no changes.
111125
*/
112-
private String fmiCacheKeyHashCache;
113-
114-
String computeFmiCacheKeyHash() {
115-
if (fmiCacheKeyHashCache != null) {
116-
return fmiCacheKeyHashCache;
117-
}
126+
private SortedMap<String, String> buildCacheKeyComponents() {
127+
TreeMap<String, String> components = null;
118128
if (!StringHelper.isBlank(fmiPath)) {
119-
TreeMap<String, String> components = new TreeMap<>();
129+
components = new TreeMap<>();
120130
components.put("fmi_path", fmiPath);
121-
fmiCacheKeyHashCache = StringHelper.computeExtCacheKeyHash(components);
122-
} else {
123-
fmiCacheKeyHashCache = "";
124131
}
125-
return fmiCacheKeyHashCache;
132+
return components;
133+
}
134+
135+
/**
136+
* Returns the extended cache key components for this request, if any.
137+
* Used by {@link TokenCache} for both cache writes and reads.
138+
*/
139+
SortedMap<String, String> cacheKeyComponents() {
140+
return this.cacheKeyComponents;
141+
}
142+
143+
/**
144+
* Computes the extended cache key hash from all cache key components.
145+
* Returns an empty string if no components are present.
146+
* <p>
147+
* The result is memoized since ClientCredentialParameters is immutable after construction.
148+
* Used by both cache writes ({@link TokenCache}) and cache reads (silent lookup).
149+
*/
150+
String computeExtCacheKeyHash() {
151+
if (extCacheKeyHashCache != null) {
152+
return extCacheKeyHashCache;
153+
}
154+
extCacheKeyHashCache = StringHelper.computeExtCacheKeyHash(cacheKeyComponents);
155+
return extCacheKeyHashCache;
126156
}
127157

128158
public static class ClientCredentialParametersBuilder {

msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/TokenCache.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -339,12 +339,12 @@ private static AccessTokenCacheEntity createAccessTokenCacheEntity(TokenRequestE
339339

340340
/**
341341
* Computes the extended cache key hash for a request, if applicable.
342-
* Currently, this is used for client credential requests with an fmi_path parameter.
342+
* Delegates to the generic cache key components on the parameters object.
343343
* The algorithm uses sorted key-value concatenation → SHA-256 → Base64URL (cross-SDK compatible).
344344
*/
345345
private static String computeExtCacheKeyHashForRequest(MsalRequest msalRequest) {
346346
if (msalRequest instanceof ClientCredentialRequest) {
347-
return ((ClientCredentialRequest) msalRequest).parameters.computeFmiCacheKeyHash();
347+
return ((ClientCredentialRequest) msalRequest).parameters.computeExtCacheKeyHash();
348348
}
349349
return "";
350350
}

0 commit comments

Comments
 (0)