Skip to content

Fix Key Vault challenge-based authentication tenant ID parsing for DSTSv2 authorities - #50450

Open
prasanna164-code wants to merge 2 commits into
Azure:mainfrom
prasanna164-code:keyvault-dstsv2-tenant
Open

prasanna164-code wants to merge 2 commits into
Azure:mainfrom
prasanna164-code:keyvault-dstsv2-tenant

Conversation

@prasanna164-code

@prasanna164-code prasanna164-code commented Sep 15, 2026

Copy link
Copy Markdown

Description

Fixes #48088

The Key Vault challenge-based authentication policy (KeyVaultCredentialPolicy) extracts the tenant ID from the authorization / authorization_uri parameter of the WWW-Authenticate challenge by taking the first path segment of the URI. That is correct for Microsoft Entra ID authorities (https://login.microsoftonline.com/{tenantId}), but DSTSv2 authorities have the form https://<host>/dstsv2/{tenantId}, so the literal string dstsv2 was passed to the credential as the tenant ID and token acquisition failed or targeted the wrong tenant.

This change detects the dstsv2 path segment (case-insensitively) and reads the tenant ID from the segment that follows it, matching the fix that shipped in the .NET libraries in Azure/azure-sdk-for-net#56416. All other authorization URIs are parsed exactly as before.

The fix is applied to every copy of KeyVaultCredentialPolicy:

  • com.azure (track 2): azure-security-keyvault-keys, -secrets, -certificates, -administration
  • com.azure.v2: azure-security-keyvault-keys, -secrets, -certificates, -administration

CHANGELOG entries were added under Bugs Fixed for the four com.azure libraries. The com.azure.v2 libraries have not shipped yet, so their changelogs were left untouched.

Testing

New tests in KeyVaultCredentialPolicyTest for each of the four com.azure libraries (sync and async via @SyncAsyncTest):

  • onChallengeExtractsTenantIdFromEntraAuthorizationUri - pins the existing behavior for Entra ID authorities by asserting the exact tenant ID passed to the TokenCredential.
  • onChallengeExtractsTenantIdFromDstsV2AuthorizationUri - asserts the tenant ID that follows dstsv2 is passed to the credential.
  • processDstsV2ChallengeResponse - full 401 -> 200 pipeline flow against a DSTSv2 challenge, mirroring the .NET test.

New KeyVaultCredentialPolicyTest for each of the four com.azure.v2 libraries, driving the policy through a clientcore HttpPipeline:

  • onChallengeExtractsTenantIdFromEntraAuthorizationUri / onChallengeExtractsTenantIdFromDstsV2AuthorizationUri - assert the tenant ID passed to the credential and the 401 -> 200 retry.
  • onChallengeCachedForSubsequentRequests - a later request is authorized from the cached challenge with the DSTSv2 tenant and no extra 401.

The keys, certificates and administration com.azure.v2 modules gain the same JUnit test dependencies the secrets module already declares.

Without the source change the DSTSv2 tests fail with expected: <de763a21-...> but was: <dstsv2>, confirming they cover the bug.

Verified locally with JDK 21:

  • KeyVaultCredentialPolicyTest: 35 tests green in each of the four com.azure libraries.
  • Checkstyle and SpotBugs: 0 violations in the four com.azure libraries.
  • The four com.azure.v2 libraries: 3 tests green each with 0 Checkstyle violations, built against locally built io.clientcore:core and com.azure.v2:azure-core.

All SDK Contribution checklist:

  • The pull request does not introduce [breaking changes]
  • CHANGELOG is updated for new features, bug fixes or other significant changes.
  • I have read the contribution guidelines.

General Guidelines and Best Practices

  • Title of the pull request is clear and informative.
  • There are a small number of commits, each of which have an informative message. This means that previously merged commits do not appear in the history of the PR. For more information on cleaning up the commits in your PR, see this page.

Testing Guidelines

  • Pull request includes test coverage for the included changes.

The challenge-based authentication policy assumed the tenant ID is always the
first path segment of the challenge's authorization URI. DSTSv2 authorities use
the form https://<host>/dstsv2/<tenantId>, so the literal string "dstsv2" was
used as the tenant ID and token acquisition targeted the wrong tenant.

Detect the "dstsv2" path segment and read the tenant ID from the segment that
follows it, matching the behavior of the .NET Key Vault libraries.

Applied to the keys, secrets, certificates and administration libraries for
both com.azure and com.azure.v2. Added sync and async unit tests covering
Microsoft Entra ID and DSTSv2 authorization URIs, and a full 401 -> 200
pipeline flow against a DSTSv2 challenge.

Fixes Azure#48088
Copilot AI lite review requested due to automatic review settings September 15, 2026 00:06
@prasanna164-code
prasanna164-code requested review from a team as code owners September 15, 2026 00:06
@github-actions github-actions Bot added Community Contribution Community members are working on the issue customer-reported Issues that are reported by GitHub users external to the Azure organization. KeyVault labels Sep 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Thank you for your contribution prasanna164-code! We will review the pull request and get back to you soon.

@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 1 pipeline(s).
31 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@prasanna164-code

Copy link
Copy Markdown
Author

@microsoft-github-policy-service agree

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The v2 policy implementations lack direct sync/async challenge tests, so final human review is warranted.

Pull request overview

Fixes Key Vault challenge authentication tenant parsing for DSTSv2 authorities across current and v2 implementations.

Changes:

  • Parses the tenant ID after the case-insensitive dstsv2 path segment.
  • Adds sync/async regression tests for the four current libraries.
  • Updates changelogs for the current libraries.
File summaries
File Summary
sdk/keyvault/azure-security-keyvault-secrets/src/test/java/com/azure/security/keyvault/secrets/KeyVaultCredentialPolicyTest.java Authentication parsing and challenge-flow tests
sdk/keyvault/azure-security-keyvault-secrets/src/main/java/com/azure/security/keyvault/secrets/implementation/KeyVaultCredentialPolicy.java DSTSv2 tenant parsing fix
sdk/keyvault/azure-security-keyvault-secrets/CHANGELOG.md Bug fix entry
sdk/keyvault/azure-security-keyvault-keys/src/test/java/com/azure/security/keyvault/keys/KeyVaultCredentialPolicyTest.java Authentication parsing and challenge-flow tests
sdk/keyvault/azure-security-keyvault-keys/src/main/java/com/azure/security/keyvault/keys/implementation/KeyVaultCredentialPolicy.java DSTSv2 tenant parsing fix
sdk/keyvault/azure-security-keyvault-keys/CHANGELOG.md Bug fix entry
sdk/keyvault/azure-security-keyvault-certificates/src/test/java/com/azure/security/keyvault/certificates/KeyVaultCredentialPolicyTest.java Authentication parsing and challenge-flow tests
sdk/keyvault/azure-security-keyvault-certificates/src/main/java/com/azure/security/keyvault/certificates/implementation/KeyVaultCredentialPolicy.java DSTSv2 tenant parsing fix
sdk/keyvault/azure-security-keyvault-certificates/CHANGELOG.md Bug fix entry
sdk/keyvault/azure-security-keyvault-administration/src/test/java/com/azure/security/keyvault/administration/KeyVaultCredentialPolicyTest.java Authentication parsing and challenge-flow tests
sdk/keyvault/azure-security-keyvault-administration/src/main/java/com/azure/security/keyvault/administration/implementation/KeyVaultCredentialPolicy.java DSTSv2 tenant parsing fix
sdk/keyvault/azure-security-keyvault-administration/CHANGELOG.md Bug fix entry
sdk/keyvault-v2/azure-security-keyvault-secrets/src/main/java/com/azure/v2/security/keyvault/secrets/implementation/KeyVaultCredentialPolicy.java DSTSv2 tenant parsing fix
sdk/keyvault-v2/azure-security-keyvault-keys/src/main/java/com/azure/v2/security/keyvault/keys/implementation/KeyVaultCredentialPolicy.java DSTSv2 tenant parsing fix
sdk/keyvault-v2/azure-security-keyvault-certificates/src/main/java/com/azure/v2/security/keyvault/certificates/implementation/KeyVaultCredentialPolicy.java DSTSv2 tenant parsing fix
sdk/keyvault-v2/azure-security-keyvault-administration/src/main/java/com/azure/v2/security/keyvault/administration/implementation/KeyVaultCredentialPolicy.java DSTSv2 tenant parsing fix
Review details

Suppressed comments (4)

sdk/keyvault-v2/azure-security-keyvault-administration/src/main/java/com/azure/v2/security/keyvault/administration/implementation/KeyVaultCredentialPolicy.java:320

  • This v2 implementation adds the DSTSv2 parsing branch, but the v2 Key Vault packages do not have a KeyVaultCredentialPolicy test (the only discovered v2 test is a disabled client test). The v1 tests do not exercise this separate com.azure.v2 implementation, so a regression here could still compile while passing dstsv2 as the tenant; add sync and async challenge coverage for the v2 policy before relying on the v1 tests.
            if (DSTS_V2_PATH_SEGMENT.equalsIgnoreCase(tenantId)
                && pathSegments.length > 2
                && !pathSegments[2].isEmpty()) {
                tenantId = pathSegments[2];

sdk/keyvault-v2/azure-security-keyvault-certificates/src/main/java/com/azure/v2/security/keyvault/certificates/implementation/KeyVaultCredentialPolicy.java:320

  • This v2 implementation adds the DSTSv2 parsing branch, but the v2 Key Vault packages do not have a KeyVaultCredentialPolicy test (the only discovered v2 test is a disabled client test). The v1 tests do not exercise this separate com.azure.v2 implementation, so a regression here could still compile while passing dstsv2 as the tenant; add sync and async challenge coverage for the v2 policy before relying on the v1 tests.
            if (DSTS_V2_PATH_SEGMENT.equalsIgnoreCase(tenantId)
                && pathSegments.length > 2
                && !pathSegments[2].isEmpty()) {
                tenantId = pathSegments[2];

sdk/keyvault-v2/azure-security-keyvault-keys/src/main/java/com/azure/v2/security/keyvault/keys/implementation/KeyVaultCredentialPolicy.java:320

  • This v2 implementation adds the DSTSv2 parsing branch, but the v2 Key Vault packages do not have a KeyVaultCredentialPolicy test (the only discovered v2 test is a disabled client test). The v1 tests do not exercise this separate com.azure.v2 implementation, so a regression here could still compile while passing dstsv2 as the tenant; add sync and async challenge coverage for the v2 policy before relying on the v1 tests.
            if (DSTS_V2_PATH_SEGMENT.equalsIgnoreCase(tenantId)
                && pathSegments.length > 2
                && !pathSegments[2].isEmpty()) {
                tenantId = pathSegments[2];

sdk/keyvault-v2/azure-security-keyvault-secrets/src/main/java/com/azure/v2/security/keyvault/secrets/implementation/KeyVaultCredentialPolicy.java:320

  • This v2 implementation adds the DSTSv2 parsing branch, but the v2 Key Vault packages do not have a KeyVaultCredentialPolicy test (the only discovered v2 test is a disabled client test). The v1 tests do not exercise this separate com.azure.v2 implementation, so a regression here could still compile while passing dstsv2 as the tenant; add sync and async challenge coverage for the v2 policy before relying on the v1 tests.
            if (DSTS_V2_PATH_SEGMENT.equalsIgnoreCase(tenantId)
                && pathSegments.length > 2
                && !pathSegments[2].isEmpty()) {
                tenantId = pathSegments[2];
  • Files reviewed: 16/16 changed files
  • Comments generated: 0
  • Review effort level: Lite

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

…raries

The com.azure.v2 libraries had no coverage of their KeyVaultCredentialPolicy,
so the DSTSv2 fix there was only verified by compilation. Add tests that drive
the policy through a clientcore HttpPipeline and assert the tenant ID passed
to the credential for Microsoft Entra ID and DSTSv2 authorization URIs, the
401 -> 200 retry, and reuse of the cached challenge on a later request.

The keys, certificates and administration modules gain the same JUnit test
dependencies the secrets module already declares.
@prasanna164-code

Copy link
Copy Markdown
Author

Added KeyVaultCredentialPolicy tests for the four com.azure.v2 libraries as well (d868571), since those copies previously had no test coverage. They run the policy through a clientcore HttpPipeline and check the tenant ID passed to the credential for Entra ID and DSTSv2 authorities, the 401 -> 200 retry, and the cached challenge on a later request. The keys, certificates and administration v2 modules needed the same JUnit test dependencies the secrets module already had.

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

Labels

Community Contribution Community members are working on the issue customer-reported Issues that are reported by GitHub users external to the Azure organization. KeyVault

Projects

Status: Untriaged

Development

Successfully merging this pull request may close these issues.

Key Vault challenge-based authentication fails to extract tenant ID from DSTSv2 authority URIs

2 participants