Fix Key Vault challenge-based authentication tenant ID parsing for DSTSv2 authorities - #50450
prasanna164-code wants to merge 2 commits into
Conversation
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
|
Thank you for your contribution prasanna164-code! We will review the pull request and get back to you soon. |
|
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. |
|
@microsoft-github-policy-service agree |
There was a problem hiding this comment.
🔵 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
dstsv2path 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
KeyVaultCredentialPolicytest (the only discovered v2 test is a disabled client test). The v1 tests do not exercise this separatecom.azure.v2implementation, so a regression here could still compile while passingdstsv2as 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
KeyVaultCredentialPolicytest (the only discovered v2 test is a disabled client test). The v1 tests do not exercise this separatecom.azure.v2implementation, so a regression here could still compile while passingdstsv2as 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
KeyVaultCredentialPolicytest (the only discovered v2 test is a disabled client test). The v1 tests do not exercise this separatecom.azure.v2implementation, so a regression here could still compile while passingdstsv2as 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
KeyVaultCredentialPolicytest (the only discovered v2 test is a disabled client test). The v1 tests do not exercise this separatecom.azure.v2implementation, so a regression here could still compile while passingdstsv2as 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.
|
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. |
Description
Fixes #48088
The Key Vault challenge-based authentication policy (
KeyVaultCredentialPolicy) extracts the tenant ID from theauthorization/authorization_uriparameter of theWWW-Authenticatechallenge 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 formhttps://<host>/dstsv2/{tenantId}, so the literal stringdstsv2was passed to the credential as the tenant ID and token acquisition failed or targeted the wrong tenant.This change detects the
dstsv2path 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,-administrationcom.azure.v2:azure-security-keyvault-keys,-secrets,-certificates,-administrationCHANGELOG entries were added under Bugs Fixed for the four
com.azurelibraries. Thecom.azure.v2libraries have not shipped yet, so their changelogs were left untouched.Testing
New tests in
KeyVaultCredentialPolicyTestfor each of the fourcom.azurelibraries (sync and async via@SyncAsyncTest):onChallengeExtractsTenantIdFromEntraAuthorizationUri- pins the existing behavior for Entra ID authorities by asserting the exact tenant ID passed to theTokenCredential.onChallengeExtractsTenantIdFromDstsV2AuthorizationUri- asserts the tenant ID that followsdstsv2is passed to the credential.processDstsV2ChallengeResponse- full401 -> 200pipeline flow against a DSTSv2 challenge, mirroring the .NET test.New
KeyVaultCredentialPolicyTestfor each of the fourcom.azure.v2libraries, driving the policy through a clientcoreHttpPipeline:onChallengeExtractsTenantIdFromEntraAuthorizationUri/onChallengeExtractsTenantIdFromDstsV2AuthorizationUri- assert the tenant ID passed to the credential and the401 -> 200retry.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.v2modules 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 fourcom.azurelibraries.com.azurelibraries.com.azure.v2libraries: 3 tests green each with 0 Checkstyle violations, built against locally builtio.clientcore:coreandcom.azure.v2:azure-core.All SDK Contribution checklist:
General Guidelines and Best Practices
Testing Guidelines