ITADN

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

#6967Openchristothes 创建于 2026-02-24
Clientneeds-team-triageKeyVault
C
christothescommented
# Key Vault challenge-based authentication fails to extract tenant ID from DSTSv2 authority URIs ## Summary The Key Vault challenge-based authentication policy incorrectly parses the tenant ID from `WWW-Authenticate` challenge responses when the authorization URI uses a DSTSv2 (Distributed Security Token Service v2) authority format. This causes authentication failures when connecting to Key Vault endpoints that return DSTSv2 challenges. ## Background When a Key Vault client makes an unauthenticated request, the service responds with a `401 Unauthorized` containing a `WWW-Authenticate` header like: ``` Bearer authorization="https://login.microsoftonline.com/{tenantId}", resource="https://vault.azure.net" ``` The client parses the `authorization` URI to extract the tenant ID (typically the first path segment) and uses it to acquire a token. ## The Bug The current implementation assumes the tenant ID is always the **first path segment** of the authorization URI. This is correct for standard Entra ID (AAD) authorities: ``` https://login.microsoftonline.com/{tenantId}/oauth2/authorize ^^^^^^^^^ Segments[1] = tenantId ✅ ``` However, DSTSv2 authority URIs have a **different path layout** where `dstsv2` is the first path segment and the tenant ID is the **second**: ``` https://uswest2-passive-dsts.dsts.core.windows.net/dstsv2/{tenantId} ^^^^^^ ^^^^^^^^^ Seg[1] Seg[2] = tenantId ``` With the current logic, the extracted "tenant ID" is the literal string `dstsv2` instead of the actual GUID, causing token acquisition to fail or target the wrong tenant. ### Example challenge header from a DSTSv2 endpoint ``` Bearer authorization="https://uswest2-passive-dsts.dsts.core.windows.net/dstsv2/de763a21-49f7-4b08-a8e1-52c8fbc103b4", resource="https://foo.bar.core.windows.net" ``` ## Expected Behavior The tenant ID should be correctly extracted as `de763a21-49f7-4b08-a8e1-52c8fbc103b4`, regardless of whether the authority URI is a standard Entra ID endpoint or a DSTSv2 endpoint. ## Fix Description When parsing the authorization URI to extract the tenant ID: 1. Extract the first path segment as usual. 2. If the first path segment equals `dstsv2` (case-insensitive) **and** there is a subsequent path segment, use that subsequent segment as the tenant ID instead. ### Pseudocode ``` tenantId = authorizationUri.pathSegments[1] // e.g. "dstsv2" or a GUID if tenantId.equalsIgnoreCase("dstsv2") AND pathSegments.length > 2: tenantId = authorizationUri.pathSegments[2] ``` ## Affected Area This bug is in the **Key Vault challenge-based authentication policy** — the component that handles the `401 → parse challenge → acquire token → retry` flow. In each language SDK, this is typically: | Language | Approximate Location | |----------|---------------------| | .NET | `ChallengeBasedAuthenticationPolicy.ChallengeParameters` constructor | | Python | `ChallengeAuthPolicy` / `HttpChallenge` class | | Java | `KeyVaultCredentialPolicy` | | JavaScript/TypeScript | `challengeBasedAuthenticationPolicy` / challenge parsing utilities | | Go | `challengePolicy` / challenge parsing in `azkeys`, `azsecrets`, `azcertificates` | ## Reference Fix The .NET fix is in [Azure/azure-sdk-for-net#56416](https://github.com/Azure/azure-sdk-for-net/pull/56416). Key change in `ChallengeBasedAuthenticationPolicy.cs`: ```csharp TenantId = authorizationUri.Segments[1].Trim('/'); if (TenantId.Equals("dstsv2", StringComparison.OrdinalIgnoreCase) && authorizationUri.Segments.Length > 2) { TenantId = authorizationUri.Segments[2].Trim('/'); } ``` ## Suggested Test Case Simulate a Key Vault challenge response with a DSTSv2 authorization URI and verify the tenant ID is correctly extracted: 1. Mock a `401` response with header: ``` WWW-Authenticate: Bearer authorization="https://uswest2-passive-dsts.dsts.core.windows.net/dstsv2/{expectedTenantGuid}", resource="https://foo.bar.core.windows.net" ``` 2. Mock a `200` response for the subsequent authenticated request. 3. Capture the tenant ID passed to the credential's `getToken` call. 4. Assert the captured tenant ID equals the expected GUID, **not** the literal string `"dstsv2"`. ## Labels `KeyVault`, `bug`, `client`
0 条评论