Fix: Honor MSA tenant GUID when specified via WithTenantId at request level#5958
Merged
Conversation
… level
When a ConfidentialClientApplication is configured with a specific tenant
at the app level, calling .WithTenantId('9188040d-...') (the MSA/consumer
tenant GUID) at the request level was silently ignored.
Root cause: IsCommonOrganizationsOrConsumersTenant() equates both the
'consumers' string alias and the MSA GUID as tenantless, causing the
request-level override to be discarded.
Fix: Add IsConsumersGuid() helper to AadAuthority that returns true only
for the MSA GUID (not the 'consumers' alias). Use it in the request
authority resolution condition in CreateAuthorityForRequestAsync so the
GUID is honored as a real tenant ID at request level.
The 'consumers' string alias continues to be ignored at request level
per the existing known limitation (#2929).
Fixes #5951
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…iltering GetTenantedAuthority (AadAuthority): the MSA tenant GUID is a real tenant ID and should not be replaced by a caller-supplied tenant when forceSpecifiedTenant=false. Previously IsCommonOrganizationsOrConsumersTenant() returned true for the GUID, causing it to be replaced like 'common' or 'consumers'. Added && !IsConsumersGuid() guard to preserve the GUID unless replacement is explicitly forced. FilterTokensByHomeAccountTenantOrAssertion (OBO cache): the same root cause meant OBO cache lookups with the MSA GUID as authority set filterByTenantId=false, logging a spurious 'Please use tenanted authority' warning and skipping tenant filtering. Fixed by treating the MSA GUID as a tenanted authority in the filter expression. Test: GetTenantedAuthority_MsaGuid_IsNotReplaced in AadAuthorityTests covers both forceSpecifiedTenant=false (preserved) and =true (replaced) cases. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
gladjohn
reviewed
Apr 28, 2026
bgavrilMS
reviewed
Apr 28, 2026
bgavrilMS
reviewed
Apr 28, 2026
The MSA tenant GUID (9188040d-6c67-4c5b-b112-36a304b66dad) is a real, concrete tenant ID — not a tenantless alias like 'consumers', 'common', or 'organizations'. The previous fix added IsConsumersGuid() guards in four places; this commit fixes the predicate itself instead. Changes: - AadAuthority.IsCommonOrganizationsOrConsumersTenant: replace IsConsumers(tenantId) with a plain 'consumers' string equality check, so only the alias string is tenantless — not the GUID - Remove IsConsumersGuid() instance and static helpers (no longer needed) - Remove the four IsConsumersGuid() guards that compensated for the incorrect predicate behavior - Add predicate unit test asserting MSA GUID returns false - Add Bearer token mocked HTTP test (issue #5951) asserting the token request targets the MSA tenant endpoint, not 'common' Fixes #5951 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- ConfidentialClientApplicationTests: change ClientCreds_WithTenantId_MsaGuid test to configure app with MSA GUID authority and override with a different tenant at request level, validating that the override fires (not the app-level MSA GUID) - AuthorityTests: refactor WithTenantId_ConsumerGuid_IsHonoredAtRequestLevel from inline cases to [DataRow] with descriptive DisplayNames for easier reading in the test runner Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
neha-bhargava
approved these changes
May 7, 2026
neha-bhargava
left a comment
Contributor
There was a problem hiding this comment.
Looks good. Thanks
4gust
approved these changes
May 11, 2026
bgavrilMS
reviewed
May 11, 2026
…equest-level tenant relaxation - Delete the misleading IsCommonOrganizationsOrConsumersTenant helper (both instance and static overloads) — it conflated truly tenantless aliases (common/organizations) with real tenant identifiers (consumers/MSA GUID). - Remove 'consumers' from s_tenantlessTenantNames to match the semantic model: only 'common' and 'organizations' are tenantless. - Replace all 6 call sites with IsCommonOrOrganizationsTenant: AadAuthority.GetTenantedAuthority, AuthorityInfo.CreateAuthorityForRequestAsync, CiamAuthority.GetTenantedAuthority, DstsAuthority.GetTenantedAuthority, MtlsPopParametersInitializer, TokenCache.FilterTokensByHomeAccountTenantOrAssertion. - Full relaxation: any request-level tenant that is not 'common' or 'organizations' (including 'consumers' string and the MSA GUID) is now honored at request level. - Update AuthorityTests DataRows: consumers at request level now wins instead of being ignored (AppSpecificTenant_RequestConsumersAlias_ConsumersWins, AppCommon_RequestConsumersAlias_ConsumersWins). - Delete IsCommonOrganizationsOrConsumersTenant_MsaGuid_ReturnsFalse test (method no longer exists). - Delete MtlsPop_WithMsaTenantGuidAuthority_DoesNotThrowMissingTenantedAuthority test per Bogdan's review — covered by the bearer token regression test. Fixes #5951 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
GetAuthorizationRequestUrl_WithConsumerInCreate_ReturnsConsumers was asserting StartsWith(Constants.Common) but the test name says 'ReturnsConsumers'. The PR fix correctly routes consumers authority, so update the assertion to match the intended behavior. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
bgavrilMS
approved these changes
May 11, 2026
Member
|
LGTM |
Robbie-Microsoft
added a commit
that referenced
this pull request
May 12, 2026
Remove 'consumers' from the list of tenants that should only be set at app level. Since PR #5958, 'consumers' and the MSA GUID are real tenant identifiers honored at request level; only 'common' and 'organizations' are tenantless aliases that are ignored at request level. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Robbie-Microsoft
added a commit
that referenced
this pull request
May 28, 2026
… follow-up) Follow-up to #5958 addressing reviewer feedback (#5958 (comment)): - CiamAuthority: remove dead/unreachable code paths in GetTenantedAuthority. - DstsAuthority: keep the silent-flow rewrite path that Authority.CreateAuthorityWithTenant relies on (tenantless dstsv2/common / dstsv2/organizations configured authorities must be rewritten to the tenanted form even when forceSpecifiedTenant is false), and document the contract in a comment. Adds two regression tests covering the non-forced rewrite for both `common` and `organizations`. - AuthorityInfo: tighten an XML doc comment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Robbie-Microsoft
added a commit
that referenced
this pull request
May 28, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #5951
When a
ConfidentialClientApplicationis configured with a specific tenant at the app level, calling.WithTenantId("9188040d-6c67-4c5b-b112-36a304b66dad")(the MSA/consumer tenant GUID) or.WithTenantId("consumers")at request level was silently ignored — the app-level authority was used instead.Root Cause
IsCommonOrganizationsOrConsumersTenant()incorrectly treated"consumers"(and the MSA tenant GUID it resolves to) as tenantless aliases on par with"common"/"organizations". This caused request-level tenant overrides using either form to be discarded.The correct distinction is:
"common"/"organizations"→ genuinely tenantless; request-level override should be ignored"consumers"/"9188040d-6c67-4c5b-b112-36a304b66dad"→ real tenant identifiers; should be honored at request levelChanges
AadAuthority.csIsCommonOrganizationsOrConsumersTenant()(both instance and static overloads) — the misleading helper that conflated tenantless aliases with real tenant IDs"consumers"froms_tenantlessTenantNames— only"common"and"organizations"are truly tenantlessGetTenantedAuthority()to useIsCommonOrOrganizationsTenant()so the"consumers"alias and MSA GUID are preserved rather than substitutedAuthorityInfo.csFixed
CreateAuthorityForRequestAsyncto useIsCommonOrOrganizationsTenant()— request-level"consumers"and MSA GUID are now both honored as real tenants. Updated XML doc comment.MtlsPopParametersInitializer.csFixed the mTLS PoP validation that rejects non-tenanted authorities: replaced
IsCommonOrganizationsOrConsumersTenantwithIsCommonOrOrganizationsTenantso apps using the MSA GUID as their authority are no longer incorrectly rejected.TokenCache.ITokenCacheInternal.csFixed OBO cache filtering: replaced
IsCommonOrganizationsOrConsumersTenantwithIsCommonOrOrganizationsTenantso the MSA GUID is treated as a real tenanted authority and tenant-based cache filtering is applied correctly.CiamAuthority.cs/DstsAuthority.csReplaced
IsCommonOrganizationsOrConsumersTenantwithIsCommonOrOrganizationsTenantinGetTenantedAuthorityoverrides.Tests
AuthorityTests.cs—WithTenantId_ConsumerGuid_IsHonoredAtRequestLevelcommon"consumers"stringconsumerswinscommon"consumers"stringconsumerswinsAadAuthorityTests.csRemoved
IsCommonOrganizationsOrConsumersTenant_MsaGuid_ReturnsFalse— the helper no longer exists.