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

MsalUiRequiredException: No account or login hint. Token cache selected with wrong key. #222

Closed
jnaglis opened this issue Jun 19, 2020 · 3 comments
Assignees
Labels
bug Something isn't working duplicate This issue or pull request already exists fixed

Comments

@jnaglis
Copy link

jnaglis commented Jun 19, 2020

Which Version of Microsoft Identity Web are you using ?
Note that to get help, you need to run the latest version.
Where is the issue?

  • Web App
    ○  Sign-in users
    ○  Sign-in users and call web APIs
  • Web API
    ○  Protected web APIs (Validating tokens)
    ○  Protected web APIs (Validating scopes)
    [X] Protected web APIs call downstream web APIs
  • Token cache serialization
    [X ] In Memory caches
    ○  Session caches
    [X] Distributed caches
    Other? - please describe;

Is this a new or existing app?
c. This is a new app or experiment

Repro
The application is pretty simple, you must be authenticated against AAD.

services.AddProtectedWebApi(Configuration)
                  .AddProtectedWebApiCallsProtectedWebApi(Configuration)
                  .AddDistributedTokenCaches();

Call Graph API on behalf of user . In Graph AuthorizationProvider getting access token :

public async Task AuthenticateRequestAsync(HttpRequestMessage request)
{
	string[] scopes = new[] { "user.read", "calendars.read" };
	string accessToken = await _tokenAcquisition.GetAccessTokenForUserAsync(scopes);
	request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
}

Token cache is stored with key - a hash of the access token used to call the Web API.

Subscribe to Graph Calendar on behalf of the user and get called back by a notification where the user is identified by his tenant id and object id (Microsoft Graph Web Hooks).

User example code found in ClaimsPrincipalFactory:

 private async Task GetChangedMessagesAsync(Ienumerable<Notification> notifications)
 {
       foreach (var notification in notifications)
       {
	   SubscriptionStore subscription = subscriptionStore.GetSubscriptionInfo(notification.SubscriptionId);
           HttpContext.User = ClaimsPrincipalExtension.FromTenantIdAndObjectId(subscription.TenantId, subscription.UserId);
           string accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
        }
 }

Actual behavior

The applciation throws MsalUiRequiredException:

MsalUiRequiredException: No account or login hint was passed to the AcquireTokenSilent call.

Debugging showed that token key returned by GetCacheKey is of structure:
**$"{userObjectId}.{tenantId}";**

Method:

private string GetCacheKey(bool isAppTokenCache)
        {
            if (isAppTokenCache)
            {
                return $"{_microsoftIdentityOptions.Value.ClientId}_AppTokenCache";
            }
            else
            {
                // In the case of Web Apps, the cache key is the user account Id, and the expectation is that AcquireTokenSilent
                // should return a token otherwise this might require a challenge.
                // In the case Web APIs, the token cache key is a hash of the access token used to call the Web API
                JwtSecurityToken jwtSecurityToken = _httpContextAccessor.HttpContext.GetTokenUsedToCallWebAPI();
                return (jwtSecurityToken != null) ? jwtSecurityToken.RawSignature
                                                                  : _httpContextAccessor.HttpContext.User.GetMsalAccountId();
            }
        }

So token cache is stored with key - a hash of the access token used to call the Web API. But then trying to get with _httpContextAccessor.HttpContext.User.GetMsalAccountId();

That's why token cache is not found.

Expected behavior
Get access token from cache.

@jennyf19 jennyf19 added the bug Something isn't working label Jun 19, 2020
@jmprieur
Copy link
Collaborator

jmprieur commented Jul 2, 2020

@jennyf19
this should be fixed by fixing #235
as we won't use GetCacheKey any longer. Yay!

@jmprieur jmprieur added the duplicate This issue or pull request already exists label Jul 2, 2020
@jmprieur jmprieur modified the milestones: 0.2.1-preview, [1] .NET 5 Readiness - 0.2.0-preview Jul 2, 2020
@jennyf19 jennyf19 added the fixed label Jul 7, 2020
@jennyf19 jennyf19 self-assigned this Jul 7, 2020
@jennyf19
Copy link
Collaborator

Included in 0.2.0-preview release

@AABhatt
Copy link

AABhatt commented Dec 22, 2021

I am using version 1.21.1 of Microsoft.Identity.Web. But still getting same error that mentioned. I have one method in Rest API to get notification. Based on subscription id, I want to further fetch resource data from graph api by user permission(not application).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working duplicate This issue or pull request already exists fixed
Projects
None yet
Development

No branches or pull requests

4 participants