Skip to content

[7.0.3 Cherry-pick] Fix Entra ID tenant parsing for multi-segment STSURL authorities - #4572

Open
github-actions[bot] wants to merge 1 commit into
release/7.0from
dev/automation/pr-4521-to-7.0.3
Open

[7.0.3 Cherry-pick] Fix Entra ID tenant parsing for multi-segment STSURL authorities#4572
github-actions[bot] wants to merge 1 commit into
release/7.0from
dev/automation/pr-4521-to-7.0.3

Conversation

@github-actions

Copy link
Copy Markdown

Cherry-pick of #4521 (89ceebc) into release/7.0.

* Fix tenant parsing for multi-segment STSURL authorities

Fixes #4496

The Dataverse/Dynamics 365 TDS endpoint returns an ADAL v1 style STSURL
("https://login.microsoftonline.com/{tenantId}/oauth2/authorize") in the
FEDAUTHINFO token. AcquireTokenAsync split the authority at the last '/',
so the tenant was parsed as the literal "authorize" and the authority host
became ".../oauth2/", causing authentication to fail.

The tenant is now taken from the first path segment of the authority URL,
ignoring trailing endpoint suffixes, and the normalized authority (host +
tenant) is used for the MSAL public client application.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b4e906c9-daf3-46f8-83e7-ef805d81fdfb

* Require an absolute HTTPS authority with a tenant

Entra ID authorities (and therefore the STSURL in FEDAUTHINFO) are always
absolute HTTPS URLs, and both MSAL's WithAuthority and Azure.Identity's
AuthorityHost require an absolute URI, so the legacy last-separator split
could never produce a working credential for anything else. Replace the
fallback with TryParseAuthority, which rejects such authorities up front
with a clear AuthenticationException instead of failing obscurely later.

Also stop re-wrapping AuthenticationException in the generic catch block.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b4e906c9-daf3-46f8-83e7-ef805d81fdfb

* Rename authority locals and TokenCredentialKey fields for clarity

Address review feedback:

- The 'audience' local no longer held the last path segment after the
  parsing fix; it holds the tenant that is passed to Azure.Identity as
  TenantId. Rename the locals and the TokenCredentialKey fields to
  authorityHost/tenant so the names match what they carry, and refresh
  the surrounding comment accordingly.
- Add a 'consumers' placeholder case to AuthorityParsingTests, which the
  TryParseAuthority documentation already calls out.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b4e906c9-daf3-46f8-83e7-ef805d81fdfb

* Use Uri.Segments to extract the tenant

Address review feedback: let the Uri class handle URI decomposition
instead of doing string manipulation on AbsolutePath.

Segments[0] is always the leading "/", so the tenant is Segments[1].
Segments retain their trailing separator when further segments follow,
so the value is trimmed. The non-empty check is kept to reject an empty
leading segment (e.g. "https://host//oauth2/authorize"), which would
otherwise yield an authority with no tenant; a test covers this.

Also fix a "DefaultAzureCredenial" typo in a comment touched by the
previous commit.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b4e906c9-daf3-46f8-83e7-ef805d81fdfb

* Normalize the password cache key and cover the remaining gaps

Address review feedback:

- GetAccountPwCacheKey keyed on the raw parameters.Authority, so two
  STSURL spellings of the same tenant produced separate password-cache
  entries. It now takes the normalized authority, consistent with the
  rest of this change. The userId parameter is nullable to preserve the
  previous concatenation behavior.
- Add a test asserting AcquireTokenAsync surfaces the authority
  AuthenticationException unwrapped, so reordering the catch blocks
  can't silently regress it back to "Unexpected error". Verified the
  test fails when the pass-through catch is removed.
- Add http:// cases to the rejection theory so the HTTPS requirement is
  pinned by a test, and rename the theory accordingly.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b4e906c9-daf3-46f8-83e7-ef805d81fdfb

---------

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: b4e906c9-daf3-46f8-83e7-ef805d81fdfb
@github-actions
github-actions Bot requested a review from a team as a code owner August 21, 2026 15:54
@github-actions github-actions Bot added this to the 7.0.3 milestone Aug 21, 2026
@github-project-automation github-project-automation Bot moved this to To triage in SqlClient Board Aug 21, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

@cheenamalhotra cheenamalhotra moved this from To triage to In review in SqlClient Board Aug 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: In review

Development

Successfully merging this pull request may close these issues.

1 participant