-
Notifications
You must be signed in to change notification settings - Fork 210
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature Request] Provide an option to disable the L1 cache: Token without MFA in L1 Token Cache after MFA was requested #1388
Comments
No, I don't have a link to the code. But what we have is a custom Token Cache Adapter that inherits from
When I check the base implementation it's clear that first the L1 InMemory cache is checked. And if our app runs on multiple instances, I think that right after satisfying a Conditional Access policy, only one instance (the one that handled the re-login of the user), and of course the L2 Redis cache, contain the newly acquired token with MFA, but the rest of the L1 InMemory caches not. Why you think it should not happen? From my point of view it is bound to happen, as described above. |
can you share the code in the token cache adapter? |
here it is: public class ProtectedTokenCacheAdapter : MsalDistributedTokenCacheAdapter
{
private readonly IDataProtector protector;
public ProtectedTokenCacheAdapter(IDistributedCache memoryCache,
IOptions<MsalDistributedTokenCacheAdapterOptions> cacheOptions,
IDataProtectionProvider protectionProvider,
ILogger<MsalDistributedTokenCacheAdapter> logger) : base(memoryCache, cacheOptions, logger)
{
protector = (protectionProvider ?? throw new ArgumentNullException(nameof(protectionProvider))).CreateProtector(typeof(ProtectedTokenCacheAdapter).FullName);
}
protected override async Task<byte[]> ReadCacheBytesAsync(string cacheKey)
{
var cached = await base.ReadCacheBytesAsync(cacheKey);
try
{
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
return cached == null ? cached : protector.Unprotect(cached);
}
catch (CryptographicException)
{
// cannot unprotect this key so it should be treated as cache miss
await base.RemoveKeyAsync(cacheKey);
}
return null;
}
protected override Task WriteCacheBytesAsync(string cacheKey, byte[] bytes)
{
return base.WriteCacheBytesAsync(cacheKey, protector.Protect(bytes));
}
} |
@tjkb thank you. i think this is a scenario we didn't think about for the L1/L2 cache, but it makes sense. will probably add a way to disable the L1 cache. |
Cool, as I see it's already fixed. Any estimation when 1.16 will be available? |
@tjkb Friday (8.20) or sooner |
Included in 1.16 release |
cc @tjkb |
One of our customers has Conditional Access policies in place. This means that some Graph calls work, but for others we get a
MicrosoftIdentityWebChallengeUserException
. We handle it by letting the user login again and providing theclaims
from the exception.For Token Caching we use a distributed Redis cache.
So far, so good. But we run our Application on an Azure Web App with multiple instances. We're state-less, we have ARR Afinity disabled. Since there's a L1 InMemory cache in place by Identity.Web when using distributed cache, it means that when we get a new token for the user that complies to the Conditional Access policies, on some instances of our Web App, the L1 cache still contains the old token. Depending on the Web App instance that serves a particular API request of the user, we still get an exception. It's then basically a game of chance.
Did you think about this use case when implementing the L1 cache? How should be solve this issue? Is it possible to disable the L1 cache?
The text was updated successfully, but these errors were encountered: