diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AuthorizationCodeParameters.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AuthorizationCodeParameters.java index 66b0595f..2f4ad457 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AuthorizationCodeParameters.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/AuthorizationCodeParameters.java @@ -37,12 +37,9 @@ public class AuthorizationCodeParameters implements IAcquireTokenParameters { private String clientClaims; - // Generic extended cache key components. The hash of these components isolates cache + // Generic extended cache key. The hash of the contributed components isolates cache // entries so that requests with different client-claims values do not collide. - private SortedMap cacheKeyComponents; - - // Memoized hash of cacheKeyComponents (computed once since parameters are immutable). - private String extCacheKeyHashCache; + private final ExtendedCacheKey extendedCacheKey; private AuthorizationCodeParameters(String authorizationCode, URI redirectUri, Set scopes, ClaimsRequest claims, @@ -60,7 +57,7 @@ private AuthorizationCodeParameters(String authorizationCode, URI redirectUri, this.clientClaims = clientClaims; // Build cache key components from any parameters that require cache isolation. - this.cacheKeyComponents = buildCacheKeyComponents(); + this.extendedCacheKey = new ExtendedCacheKey(buildCacheKeyComponents()); } private static AuthorizationCodeParametersBuilder builder() { @@ -143,25 +140,13 @@ private SortedMap buildCacheKeyComponents() { return components; } - /** - * Returns the extended cache key components for this request, if any. - * Used by {@link TokenCache} for both cache writes and reads. - */ - SortedMap cacheKeyComponents() { - return this.cacheKeyComponents; - } - /** * Computes the extended cache key hash from all cache key components, or an empty string when * there are none. The result is memoized since the parameters are immutable after construction. */ @Override public String computeExtCacheKeyHash() { - if (extCacheKeyHashCache != null) { - return extCacheKeyHashCache; - } - extCacheKeyHashCache = StringHelper.computeExtCacheKeyHash(cacheKeyComponents); - return extCacheKeyHashCache; + return extendedCacheKey.computeHash(); } public static class AuthorizationCodeParametersBuilder { diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ClientCredentialParameters.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ClientCredentialParameters.java index 103ae1b8..732d22a5 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ClientCredentialParameters.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ClientCredentialParameters.java @@ -34,13 +34,10 @@ public class ClientCredentialParameters implements IAcquireTokenParameters { private String clientClaims; - // Generic extended cache key components. Any optional or flow-specific parameters - // that should influence token cache isolation adds an entry here. The hash of these - // components is used as part of the cache key in relevant scenarios entries. - private SortedMap cacheKeyComponents; - - // Memoized hash of cacheKeyComponents (computed once since parameters are immutable). - private String extCacheKeyHashCache; + // Generic extended cache key. Any optional or flow-specific parameters that should influence + // token cache isolation are contributed via buildCacheKeyComponents(); the hash of those + // components is used as part of the cache key in relevant scenarios. + private final ExtendedCacheKey extendedCacheKey; private ClientCredentialParameters(Set scopes, Boolean skipCache, ClaimsRequest claims, Map extraHttpHeaders, Map extraQueryParameters, String tenant, IClientCredential clientCredential, String fmiPath, String clientClaims) { this.scopes = scopes; @@ -54,7 +51,7 @@ private ClientCredentialParameters(Set scopes, Boolean skipCache, Claims this.clientClaims = clientClaims; // Build cache key components from any parameters that require cache isolation. - this.cacheKeyComponents = buildCacheKeyComponents(); + this.extendedCacheKey = new ExtendedCacheKey(buildCacheKeyComponents()); } private static ClientCredentialParametersBuilder builder() { @@ -149,14 +146,6 @@ private SortedMap buildCacheKeyComponents() { return components; } - /** - * Returns the extended cache key components for this request, if any. - * Used by {@link TokenCache} for both cache writes and reads. - */ - SortedMap cacheKeyComponents() { - return this.cacheKeyComponents; - } - /** * Computes the extended cache key hash from all cache key components. * Returns an empty string if no components are present. @@ -166,11 +155,7 @@ SortedMap cacheKeyComponents() { */ @Override public String computeExtCacheKeyHash() { - if (extCacheKeyHashCache != null) { - return extCacheKeyHashCache; - } - extCacheKeyHashCache = StringHelper.computeExtCacheKeyHash(cacheKeyComponents); - return extCacheKeyHashCache; + return extendedCacheKey.computeHash(); } public static class ClientCredentialParametersBuilder { diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ExtendedCacheKey.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ExtendedCacheKey.java new file mode 100644 index 00000000..a6fef8e5 --- /dev/null +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/ExtendedCacheKey.java @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.microsoft.aad.msal4j; + +import java.util.SortedMap; + +/** + * Holds the extended cache-key components contributed by a request's parameters and lazily + * computes their hash. Extended cache-key components (for example {@code fmi_path} or + * {@code client_claims}) isolate token-cache entries so that requests with different component + * values do not collide. + *

+ * Shared by the {@code *Parameters} classes that expose + * {@link IAcquireTokenParameters#computeExtCacheKeyHash()} so the storage-and-memoization + * boilerplate lives in one place instead of being copied per class. The hash is memoized because + * the owning parameters object is immutable after construction. + */ +final class ExtendedCacheKey { + + private final SortedMap components; + + // Memoized hash of the components (computed once since the owning parameters are immutable). + private String hashCache; + + ExtendedCacheKey(SortedMap components) { + this.components = components; + } + + /** + * Computes the Base64URL-encoded SHA-256 hash of the cache-key components, or an empty string + * when there are none. The result is memoized. + */ + String computeHash() { + if (hashCache == null) { + hashCache = StringHelper.computeExtCacheKeyHash(components); + } + return hashCache; + } +} diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/OnBehalfOfParameters.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/OnBehalfOfParameters.java index f328d107..1d6e8cde 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/OnBehalfOfParameters.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/OnBehalfOfParameters.java @@ -27,12 +27,9 @@ public class OnBehalfOfParameters implements IAcquireTokenParameters { private String tenant; private String clientClaims; - // Generic extended cache key components. The hash of these components isolates cache + // Generic extended cache key. The hash of the contributed components isolates cache // entries so that requests with different client-claims values do not collide. - private SortedMap cacheKeyComponents; - - // Memoized hash of cacheKeyComponents (computed once since parameters are immutable). - private String extCacheKeyHashCache; + private final ExtendedCacheKey extendedCacheKey; private OnBehalfOfParameters(Set scopes, Boolean skipCache, IUserAssertion userAssertion, ClaimsRequest claims, Map extraHttpHeaders, Map extraQueryParameters, String tenant, String clientClaims) { this.scopes = scopes; @@ -46,7 +43,7 @@ private OnBehalfOfParameters(Set scopes, Boolean skipCache, IUserAsserti this.clientClaims = clientClaims; // Build cache key components from any parameters that require cache isolation. - this.cacheKeyComponents = buildCacheKeyComponents(); + this.extendedCacheKey = new ExtendedCacheKey(buildCacheKeyComponents()); } private static OnBehalfOfParametersBuilder builder() { @@ -125,25 +122,13 @@ private SortedMap buildCacheKeyComponents() { return components; } - /** - * Returns the extended cache key components for this request, if any. - * Used by {@link TokenCache} for both cache writes and reads. - */ - SortedMap cacheKeyComponents() { - return this.cacheKeyComponents; - } - /** * Computes the extended cache key hash from all cache key components, or an empty string when * there are none. The result is memoized since the parameters are immutable after construction. */ @Override public String computeExtCacheKeyHash() { - if (extCacheKeyHashCache != null) { - return extCacheKeyHashCache; - } - extCacheKeyHashCache = StringHelper.computeExtCacheKeyHash(cacheKeyComponents); - return extCacheKeyHashCache; + return extendedCacheKey.computeHash(); } public static class OnBehalfOfParametersBuilder { diff --git a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/UserFederatedIdentityCredentialParameters.java b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/UserFederatedIdentityCredentialParameters.java index f071060e..147dfc80 100644 --- a/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/UserFederatedIdentityCredentialParameters.java +++ b/msal4j-sdk/src/main/java/com/microsoft/aad/msal4j/UserFederatedIdentityCredentialParameters.java @@ -33,12 +33,9 @@ public class UserFederatedIdentityCredentialParameters implements IAcquireTokenP private String tenant; private String clientClaims; - // Generic extended cache key components. The hash of these components isolates cache + // Generic extended cache key. The hash of the contributed components isolates cache // entries so that requests with different client-claims values do not collide. - private SortedMap cacheKeyComponents; - - // Memoized hash of cacheKeyComponents (computed once since parameters are immutable). - private String extCacheKeyHashCache; + private final ExtendedCacheKey extendedCacheKey; private UserFederatedIdentityCredentialParameters( Set scopes, @@ -63,7 +60,7 @@ private UserFederatedIdentityCredentialParameters( this.clientClaims = clientClaims; // Build cache key components from any parameters that require cache isolation. - this.cacheKeyComponents = buildCacheKeyComponents(); + this.extendedCacheKey = new ExtendedCacheKey(buildCacheKeyComponents()); } /** @@ -184,25 +181,13 @@ private SortedMap buildCacheKeyComponents() { return components; } - /** - * Returns the extended cache key components for this request, if any. - * Used by {@link TokenCache} for both cache writes and reads. - */ - SortedMap cacheKeyComponents() { - return this.cacheKeyComponents; - } - /** * Computes the extended cache key hash from all cache key components, or an empty string when * there are none. The result is memoized since the parameters are immutable after construction. */ @Override public String computeExtCacheKeyHash() { - if (extCacheKeyHashCache != null) { - return extCacheKeyHashCache; - } - extCacheKeyHashCache = StringHelper.computeExtCacheKeyHash(cacheKeyComponents); - return extCacheKeyHashCache; + return extendedCacheKey.computeHash(); } public static class UserFederatedIdentityCredentialParametersBuilder {