diff --git a/src/client/Microsoft.Identity.Client/AuthScheme/Bearer/BearerAuthenticationOperation.cs b/src/client/Microsoft.Identity.Client/AuthScheme/Bearer/BearerAuthenticationOperation.cs index 4e1dc687e9..5e5899d703 100644 --- a/src/client/Microsoft.Identity.Client/AuthScheme/Bearer/BearerAuthenticationOperation.cs +++ b/src/client/Microsoft.Identity.Client/AuthScheme/Bearer/BearerAuthenticationOperation.cs @@ -30,5 +30,11 @@ public IReadOnlyDictionary GetTokenRequestParams() // ESTS issues Bearer tokens by default, no need for any extra params return CollectionHelpers.GetEmptyDictionary(); } + + bool ValidateCachedToken(MsalCacheValidationData cachedTokenItem) + { + // no-op + return true; + } } } diff --git a/src/client/Microsoft.Identity.Client/AuthScheme/IAuthenticationOperation.cs b/src/client/Microsoft.Identity.Client/AuthScheme/IAuthenticationOperation.cs index 1ed04ea6e2..1718872d1f 100644 --- a/src/client/Microsoft.Identity.Client/AuthScheme/IAuthenticationOperation.cs +++ b/src/client/Microsoft.Identity.Client/AuthScheme/IAuthenticationOperation.cs @@ -43,6 +43,13 @@ public interface IAuthenticationOperation /// Name and values of params IReadOnlyDictionary GetTokenRequestParams(); + /// + /// + /// + /// + /// + bool ValidateCachedToken(MsalCacheValidationData cachedTokenItem); + /// /// Key ID of the public / private key pair used by the encryption algorithm, if any. /// Tokens obtained by authentication schemes that use this are bound to the KeyId, i.e. diff --git a/src/client/Microsoft.Identity.Client/AuthScheme/MsalCacheValidationData.cs b/src/client/Microsoft.Identity.Client/AuthScheme/MsalCacheValidationData.cs new file mode 100644 index 0000000000..a0e95d28c8 --- /dev/null +++ b/src/client/Microsoft.Identity.Client/AuthScheme/MsalCacheValidationData.cs @@ -0,0 +1,18 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System.Collections.Generic; + +namespace Microsoft.Identity.Client.AuthScheme +{ + /// + /// Data used to validate cache items for different authentication schemes. + /// + public class MsalCacheValidationData + { + /// + /// Gets the persisted parameters addded to the cache items. + /// + public IDictionary PersistedCacheParameters { get; internal set; } + } +} diff --git a/src/client/Microsoft.Identity.Client/AuthScheme/PoP/MtlsPopAuthenticationOperation.cs b/src/client/Microsoft.Identity.Client/AuthScheme/PoP/MtlsPopAuthenticationOperation.cs index 980ac388f7..ee79d30564 100644 --- a/src/client/Microsoft.Identity.Client/AuthScheme/PoP/MtlsPopAuthenticationOperation.cs +++ b/src/client/Microsoft.Identity.Client/AuthScheme/PoP/MtlsPopAuthenticationOperation.cs @@ -40,5 +40,11 @@ public void FormatResult(AuthenticationResult authenticationResult) { authenticationResult.BindingCertificate = _mtlsCert; } + + bool ValidateCachedToken(MsalCacheValidationData cachedTokenItem) + { + // no-op + return true; + } } } diff --git a/src/client/Microsoft.Identity.Client/AuthScheme/PoP/PopAuthenticationOperation.cs b/src/client/Microsoft.Identity.Client/AuthScheme/PoP/PopAuthenticationOperation.cs index a2723fe9b9..b52950a643 100644 --- a/src/client/Microsoft.Identity.Client/AuthScheme/PoP/PopAuthenticationOperation.cs +++ b/src/client/Microsoft.Identity.Client/AuthScheme/PoP/PopAuthenticationOperation.cs @@ -162,5 +162,11 @@ private string CreateJWS(string payload, string header) return sb.ToString(); } + + bool ValidateCachedToken(MsalCacheValidationData cachedTokenItem) + { + // no-op + return true; + } } } diff --git a/src/client/Microsoft.Identity.Client/AuthScheme/PoP/PopBrokerAuthenticationOperation.cs b/src/client/Microsoft.Identity.Client/AuthScheme/PoP/PopBrokerAuthenticationOperation.cs index c81f411f41..55dfb397be 100644 --- a/src/client/Microsoft.Identity.Client/AuthScheme/PoP/PopBrokerAuthenticationOperation.cs +++ b/src/client/Microsoft.Identity.Client/AuthScheme/PoP/PopBrokerAuthenticationOperation.cs @@ -34,5 +34,11 @@ public IReadOnlyDictionary GetTokenRequestParams() { return CollectionHelpers.GetEmptyDictionary(); } + + bool ValidateCachedToken(MsalCacheValidationData cachedTokenItem) + { + // no-op + return true; + } } } diff --git a/src/client/Microsoft.Identity.Client/AuthScheme/SSHCertificates/SSHCertAuthenticationOperation.cs b/src/client/Microsoft.Identity.Client/AuthScheme/SSHCertificates/SSHCertAuthenticationOperation.cs index cc64c2db61..198133298f 100644 --- a/src/client/Microsoft.Identity.Client/AuthScheme/SSHCertificates/SSHCertAuthenticationOperation.cs +++ b/src/client/Microsoft.Identity.Client/AuthScheme/SSHCertificates/SSHCertAuthenticationOperation.cs @@ -53,5 +53,11 @@ public IReadOnlyDictionary GetTokenRequestParams() { OAuth2Parameter.RequestConfirmation , _jwk } }; } + + bool ValidateCachedToken(MsalCacheValidationData cachedTokenItem) + { + // no-op + return true; + } } } diff --git a/src/client/Microsoft.Identity.Client/Extensibility/ExternalBoundTokenScheme.cs b/src/client/Microsoft.Identity.Client/Extensibility/ExternalBoundTokenScheme.cs index d622bbbae7..9c4fe976ff 100644 --- a/src/client/Microsoft.Identity.Client/Extensibility/ExternalBoundTokenScheme.cs +++ b/src/client/Microsoft.Identity.Client/Extensibility/ExternalBoundTokenScheme.cs @@ -37,5 +37,11 @@ public IReadOnlyDictionary GetTokenRequestParams() { return CollectionHelpers.GetEmptyDictionary(); } + + bool ValidateCachedToken(MsalCacheValidationData cachedTokenItem) + { + // no-op + return true; + } } } diff --git a/src/client/Microsoft.Identity.Client/Internal/Requests/ClientCredentialRequest.cs b/src/client/Microsoft.Identity.Client/Internal/Requests/ClientCredentialRequest.cs index e7c08f0fc8..d15aa6bb51 100644 --- a/src/client/Microsoft.Identity.Client/Internal/Requests/ClientCredentialRequest.cs +++ b/src/client/Microsoft.Identity.Client/Internal/Requests/ClientCredentialRequest.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.Identity.Client.ApiConfig.Parameters; +using Microsoft.Identity.Client.AuthScheme; using Microsoft.Identity.Client.Cache.Items; using Microsoft.Identity.Client.Core; using Microsoft.Identity.Client.Extensibility; @@ -76,6 +77,19 @@ protected override async Task ExecuteAsync(CancellationTok MsalAccessTokenCacheItem cachedAccessTokenItem = await GetCachedAccessTokenAsync().ConfigureAwait(false); + // Validate the cached token using the authentication operation + if (AuthenticationRequestParameters.AuthenticationScheme != null && + cachedAccessTokenItem != null) + { + var cacheValidationData = new MsalCacheValidationData(); + cacheValidationData.PersistedCacheParameters = cachedAccessTokenItem.PersistedCacheParameters; + if (!AuthenticationRequestParameters.AuthenticationScheme.ValidateCachedToken(cacheValidationData)) + { + logger.Info("[ClientCredentialRequest] Cached token failed authentication operation validation."); + cachedAccessTokenItem = null; + } + } + // No access token or cached access token needs to be refreshed if (cachedAccessTokenItem != null) { diff --git a/src/client/Microsoft.Identity.Client/Microsoft.Identity.Client.csproj b/src/client/Microsoft.Identity.Client/Microsoft.Identity.Client.csproj index 3279f0338a..d80d8cf17a 100644 --- a/src/client/Microsoft.Identity.Client/Microsoft.Identity.Client.csproj +++ b/src/client/Microsoft.Identity.Client/Microsoft.Identity.Client.csproj @@ -80,6 +80,7 @@ + @@ -161,4 +162,8 @@ + + + +