question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Cache key for Access Tokens differs between user type Member and user type Guest in single tenant application

See original GitHub issue

This goes along with Sample for ms-identity-aspnet-webapp-openidconnect-master throws exception on AcquireTokenSilent

Which Version of MSAL are you using ? 4.24.0

Platform ASP.NET 4.72

What authentication flow has the issue?

  • Web App
    • Authorization code Is this a new or existing app? This is a new app or experiment Repro
  • I am using an unverified AAD tenant that will be referred to as Tenant A.
  • Create an application for OIDC Authorization flow with Supported account type of Single tenant.
  • Add a user of user type Member from Tenant A.
  • Invite a guest user from a verified AAD tenant that will be referred to as Tenant B
  • Add both users to the application.
  • Create a client secret for the application
  • Copy the client id, client secret, tenant id to the web.config app settings
  • Set the redirect uri of the application to https://localhost:44388/signin-oidc

See the code in GitHub of ASP.NET project using MSAL Set a breakpoint in OnAuthorizationCodeReceivedAsync in Startup.Auth.cs right after the call to

			AuthenticationResult result = await clientApp.AcquireTokenByAuthorizationCode(new[] { "openid", "profile", "offline_access" }, notification.Code)
				.ExecuteAsync();

Run the code logging in as both users and observe the results

Add the variable result in your watch window, expand Account and look at the HomeAccountId

Expected behavior That the value used for the cache key (HomeAccountId) would be the objectid and tenant id from Tenant A for both users.

Actual behavior the value used for the cache key (HomeAccountId) for the guest user is the objectid and tenant from the AAD Tenant B.

This means that a call to IAccount account = await app.GetAccountAsync(ClaimsPrincipal.Current.GetAccountId()); will always return null for the guest user because the claims used by the GetAccountId extension will always contain values from Tenant A while the cached access token is using values from Tenant B.

Additional context/ Logs / Screenshots

Screen Shot user type Member image

Screen Shot User type Guest

image

Notice that the TenantId shows that both users are from Tenant A and that the Account is using values from Tenant B.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Reactions:1
  • Comments:13 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
jmprieurcommented, Dec 13, 2021

@kalyankrishna1 can we please update the ASP.NET sample?

1reaction
jmprieurcommented, Dec 13, 2021

MSAL.NET uses the notion HomeAccountId, which is the concatenation of the home tenant Id and the home object ID of the user. In a single tenant application, there can be guest users. Guest users are users who are invited to the tenant, and therefore, their home account id is the account id in their original (home) temant. It’s not the account id in this tenant.

To compute the home account ID, in the case of single tenant applications, you need to request the ClientInfo, which is done by updating the request to the identity provider (see here, and when the ID token come back to extract this information, which is done there

 string? clientInfo = context!.ProtocolMessage?.GetParameter(ClaimConstants.ClientInfo);

 if (!string.IsNullOrEmpty(clientInfo))
 {
  ClientInfo? clientInfoFromServer = ClientInfo.CreateFromJson(clientInfo);


  if (clientInfoFromServer != null && clientInfoFromServer.UniqueTenantIdentifier != null && clientInfoFromServer.UniqueObjectIdentifier != null)
  {
    context!.Principal!.Identities.FirstOrDefault()?.AddClaim(new Claim(ClaimConstants.UniqueTenantIdentifier, clientInfoFromServer.UniqueTenantIdentifier));
    context!.Principal!.Identities.FirstOrDefault()?.AddClaim(new Claim(ClaimConstants.UniqueObjectIdentifier, clientInfoFromServer.UniqueObjectIdentifier));
   }
  }

Indeed, the homeAccountId is retrieved by ClaimsPrincipal.GetMsalAccountId() defined here

MSAL does request the UserInfo in public client applications, but in the case of web apps, the first leg of the authorization code flow is handled by ASP.NET / ASP.NET Core / you, so … there is nothing MSAL can do about it.

If you are using ASP.NET Core, you we strongly recommend you use Microsoft.Identity.Web as it solves a number of these issues, which will hit you one after the others

Read more comments on GitHub >

github_iconTop Results From Across the Web

Acquire and cache tokens with Microsoft Authentication ...
Access tokens enable clients to securely call web APIs protected by Azure. There are several ways to acquire a token by using the...
Read more >
Define a Legacy Named Credential
Create a legacy named credential to specify the URL of a callout endpoint and its required authentication parameters in one definition. You can...
Read more >
OAuth 2.0
OAuth 2.0 lets users access instance resources through external clients by obtaining a token rather than by entering login credentials with each resource ......
Read more >
Best Practices for Application Session Management
Access tokens represent authorization and are intended to grant the bearer access to an API either on behalf of a user or an...
Read more >
Azure AD B2B user provisioning and single sign-on
These guest user accounts differ from regular Azure AD user ... User type: Members; Source: Attribute; Value: user.userprincipalname.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found