Skip to content

Source home account identifier (uid/utid) claims from the redeemed token - #3991

Open
Tanuj Sood (soodt) wants to merge 3 commits into
masterfrom
tanujsood/consistent-home-account-id-claims
Open

Source home account identifier (uid/utid) claims from the redeemed token#3991
Tanuj Sood (soodt) wants to merge 3 commits into
masterfrom
tanujsood/consistent-home-account-id-claims

Conversation

@soodt

Copy link
Copy Markdown
Contributor

Source home account identifier (uid/utid) claims from the redeemed token

  • You've read the Contributor Guide and Code of Conduct.
  • You've included unit or integration tests for your change, where applicable.
  • You've included inline docs for your change, where applicable.
  • There's an open issue for the PR that you are making. If you'd like to propose a new feature or change, please open an issue to discuss the change or find an existing issue.

Description

The web app sign-in adapters (ASP.NET Core and OWIN) now set the uid/utid claims — the
MSAL home account identifier and token-cache key — from the redeemed token's
Account.HomeAccountId instead of the client_info parameter on the sign-in response, so the
claims stay consistent with the account that was redeemed and cached.

  • No public API change — internal only (the redeemed account is carried through to the
    sign-in events).
  • B2C preserved; the existing guard for app-set uid/utid claims is retained; no claims are
    stamped when the redeemed token has no home account id.
  • Standard sign-in flows are unaffected. Unit tests added for both adapters.

The web app sign-in flow stamped the uid/utid home account identifier
claims (the MSAL home account id, used as the per-user token-cache key)
from the front-channel client_info parameter on the authorize response,
which is a separate value from the token the app actually redeems.
Derive these claims from the authoritative back-channel token result so
they are always consistent with the token that was acquired.

- Surface the home account id (HomeAccountId ObjectId/TenantId) out of
  the internal authorization-code redemption via a small internal
  AuthCodeRedemptionResult. AcquireTokenResult and all public API are
  unchanged.
- ASP.NET Core: stash the redeemed uid/utid on HttpContext.Items during
  AddAccountToCacheFromAuthorizationCodeAsync and read them in
  OnTokenValidated instead of client_info.
- OWIN: stash the redeemed uid/utid in the OWIN context / session and
  read them in SecurityTokenValidated, using namespaced storage keys.
- Preserve B2C ({oid}-{userFlow}.{utid}) handling, the reserved-claim
  conflict guard (issue 2968), and the no-account -> stamp-nothing
  behavior.
- Add unit tests for both adapters.
@soodt
Tanuj Sood (soodt) requested a review from a team as a code owner July 31, 2026 10:51
@bgavrilMS

Copy link
Copy Markdown
Member

Tanuj Sood (@soodt) - what bug are you trying to solve? This s a pretty tricky area of the code.

What testing has there been done. You need to manually test:

  • reopening from cached session
  • case where access token is expired and Id.Web uses AcquireTokenSilent

}
httpContext.Session.Remove(ClaimConstants.ClientInfo);
}
(string? homeObjectId, string? homeTenantId) = GetAndRemoveHomeAccountIdentifier(context.OwinContext, httpContext);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need to do: Get & Remove and then Add ? Why not just GetOrAdd ?

@@ -161,11 +161,21 @@ public TokenAcquisition(
#endif
public async Task<AcquireTokenResult> AddAccountToCacheFromAuthorizationCodeAsync(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need this overload?

@bgavrilMS Bogdan Gavril (bgavrilMS) left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not clear what problem is solved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants