Skip to content
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

"The cache contains multiple tokens" error can occur if "openid", "profile" or "offline_access" scopes are requested #2998

Open
edahlberg opened this issue Aug 26, 2024 · 4 comments
Labels
enhancement New feature or request feature request

Comments

@edahlberg
Copy link

edahlberg commented Aug 26, 2024

Microsoft.Identity.Web Library

Microsoft.Identity.Web.TokenAcquisition

Microsoft.Identity.Web version

3.1.0

Web app

Sign-in users and call web APIs

Web API

Protected web APIs call downstream web APIs

Token cache serialization

In-memory caches

Description

When requesting tokens for any of the scopes "openid", "profile" or "offline_access", it's possible to receive Microsoft.Identity.Client.MsalClientException: The cache contains multiple tokens satisfying the requirements. Try to clear token cache.

This happens because when getting tokens from cache, these three scopes are explicitly ignored because they're "required" scopes. Code can be seen in TokenAcquisition.cs. -> scopes.Except(_scopesRequestedByMsal). This means that a token with any scope will pass the requirements.

Reproduction steps

  1. With a configured application that can call downstream scopes, add a controller with the included code snippet below

  2. Replace the custom api scope with a real downstream api/scope the application can access.

  3. When called, the "var c" line will always throw Microsoft.Identity.Client.MsalClientException: The cache contains multiple tokens satisfying the requirements. Try to clear token cache.

Error message

Microsoft.Identity.Client.MsalClientException: 'The cache contains multiple tokens satisfying the requirements. Try to clear token cache. '

This exception was originally thrown at this call stack:
    Microsoft.Identity.Client.Internal.Requests.Silent.SilentRequest.ExecuteAsync(System.Threading.CancellationToken) in SilentRequest.cs
    Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync.AnonymousMethod__1() in RequestBase.cs
    Microsoft.Identity.Client.Utils.StopwatchService.MeasureCodeBlockAsync(System.Func<System.Threading.Tasks.Task>) in StopwatchService.cs
    Microsoft.Identity.Client.Internal.Requests.RequestBase.RunAsync(System.Threading.CancellationToken) in RequestBase.cs
    Microsoft.Identity.Client.ApiConfig.Executors.ClientApplicationBaseExecutor.ExecuteAsync(Microsoft.Identity.Client.ApiConfig.Parameters.AcquireTokenCommonParameters, Microsoft.Identity.Client.ApiConfig.Parameters.AcquireTokenSilentParameters, System.Threading.CancellationToken) in ClientApplicationBaseExecutor.cs

Id Web logs

No response

Relevant code snippets

Include this in your controller with the middle api replaced.

var tokenAcquisition = this.HttpContext.RequestServices.GetRequiredService<ITokenAcquisition>();
var a = await tokenAcquisition.GetAccessTokenForUserAsync(
	scopes: ["openid"],
	user: context.Principal);
var b = await tokenAcquisition.GetAccessTokenForUserAsync(
	scopes: ["api://4208e39b-8a71-4a72-9a4c-cbdfe57b9ebf/custom:scope"], // Replace this line
	user: context.Principal);
var c = await tokenAcquisition.GetAccessTokenForUserAsync(
	scopes: ["openid"],
	user: context.Principal);

Regression

No response

Expected behavior

Either the cache should return the right token, or requesting these "required" scopes should be disallowed.

@bgavrilMS
Copy link
Member

TokenAcquisition always requests openid scope. What are you trying to achieve?

@edahlberg
Copy link
Author

@bgavrilMS

This issue is split from #13 where people were using the "openid" scope as a workaround for that issue not being fixed. This is done in one of the official examples as well:

https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/blob/master/2-WebApp-graph-user/2-6-BFF-Proxy/CallGraphBFF/Utils/CustomCookieAuthenticationEvents.cs

In that case, if any other api scope is ever requested alongside "openid", it messes up the cache. So if you were to add a downstream API call to that example project, it would have the same issue.

I didn't report this because I'm having an issue per se, but because it's wrong behavior from the cache and you asked me to do so: #13 (comment)

@jmprieur
Copy link
Collaborator

@bgavrilMS what would you advise? change in MSAL?

@bgavrilMS
Copy link
Member

The error is almost always indicative of a bug in MSAL. However, I do not understand if this is OBO scenario or auth_code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request feature request
Projects
None yet
Development

No branches or pull requests

3 participants