Key Vault challenge-based authentication fails to extract tenant ID from DSTSv2 authority URIs
Clientneeds-team-triageKeyVault
# 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 条评论