AzureAD / microsoft-authentication-library-for-dotnet

Microsoft Authentication Library (MSAL) for .NET
https://aka.ms/msal-net
MIT License
1.39k stars 340 forks source link

Client_credential should automatically cache N tokens (<500MB worth of tokens). Some form of eviction must be used and O(1) cache lookup is required. #4404

Open bgavrilMS opened 1 year ago

bgavrilMS commented 1 year ago

This is a breaking change because some applications rely on CCA object not caching objects

SamarthMayya commented 11 months ago

Hello @bgavrilMS, is this in any way related to the client credential flow of MSAL not being optimized to lookup the in-memory cache in O(1) time?

I saw that in ITokenCacheInternal, there is a method FilterTokensByScope, which filters the tokens by checking if the scopes in the requestParameters.Scopes is contained in the item.Scopes. This is O(N) lookup, if I'm not wrong.

The Accessor property for in-memory cache has a ConcurrentDictionary that can be used to lookup the cache per scope in O(1): link

This dictionary has two levels, one is a key that has ClientId_TenantId_AppTokenCache as the first key, and the second level key has the scope in it. Is there a way we can change the first key to include the scope in it, so that when we get all the access tokens, we only get the tokens cached for a particular scope?

Mainly, is there a way we can change the partition key we use to include the scope?

bgavrilMS commented 11 months ago

I agree that the lookup is not O(1), but is proportional to the number of resources an app accesses. But in our experience, this number is low, the most I have seen is ~10 resources.

We can change the logic to use the scope, however we will need to have special lookup logic for client credential flow VS user flows. In user flows, if you request "User.Read", you can get "User.Read" and "User.Write" from the STS, so we can't use scopes as key there. Today, for simplicity, we use the same cache lookup logic everywhere.

Do you have a perf problem that you are looking to solve in your app or would you like to contribute an improvement here?