fix(coding-agent): use UserTenantId for credential resolution#7078
Conversation
The extension was using Subscription.TenantId (the resource tenant) to create the AzureDeveloperCLICredential after subscription selection. For multi-tenant/guest users, this differs from Subscription.UserTenantId (the user access tenant), causing 'refresh token expired' errors. This aligns the extension with how azd core resolves credentials via SubscriptionsManager.LookupTenant(), which returns UserAccessTenantId. Fixes #7077 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes multi-tenant/guest credential resolution in the azure.coding-agent extension by using the user access tenant (the tenant the user authenticated through) rather than the subscription’s resource tenant when creating the AzureDeveloperCLICredential, aligning behavior with azd core.
Changes:
- Switch tenant selection from
Subscription.TenantIdtoSubscription.UserTenantIdwhen constructingAzureDeveloperCLICredentialOptions. - Keep subscription selection flow unchanged while ensuring the credential targets the correct tenant for token acquisition in multi-tenant scenarios.
Comments suppressed due to low confidence (1)
cli/azd/extensions/azure.coding-agent/internal/cmd/coding_agent_config.go:206
tenantIDis now sourced fromSubscription.UserTenantId(user auth tenant), but the same variable is later used to build the Azure Portal managed identity URL (the#@<tenant>segment). For guest/multi-tenant scenarios the portal blade typically needs the resource tenant (e.g.,Subscription.TenantIdorauthConfig.TenantId) to show the subscription/resource group. Suggest splitting this into two variables (e.g.,userTenantIDforAzureDeveloperCLICredentialOptions.TenantID, andresourceTenantIDfor the portal link) to avoid breaking the portal instructions flow.
tenantID := subscriptionResponse.Subscription.UserTenantId
subscriptionID := subscriptionResponse.Subscription.Id
cred, err := azidentity.NewAzureDeveloperCLICredential(&azidentity.AzureDeveloperCLICredentialOptions{
TenantID: tenantID,
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| tenantID := subscriptionResponse.Subscription.UserTenantId | ||
| subscriptionID := subscriptionResponse.Subscription.Id |
There was a problem hiding this comment.
Can we verify other extensions don't have the same issue too?
There was a problem hiding this comment.
I'll turn the engines on it :)
There was a problem hiding this comment.
Audited all extensions. Found and fixed the same bug in 5 more:
| Extension | Files | Status |
|---|---|---|
| azure.ai.models | custom.go, init.go (2 spots) | ❌ Fixed |
| azure.ai.agents | init.go, init_from_code.go | ❌ Fixed |
| azure.ai.finetune | init.go (2 spots) | ❌ Fixed |
| microsoft.azd.ai.builder | start.go | ❌ Fixed |
| microsoft.azd.demo | prompt.go | ❌ Fixed |
| azure.appservice | swap.go | ✅ Already correct (uses LookupTenant) |
| azure.ai.agents | parser.go, service_target_agent.go | ✅ Already correct (uses LookupTenant) |
Pushed in b5c9ebf.
There was a problem hiding this comment.
It was me the entire time! :|
…7078) The extension was using Subscription.TenantId (the resource tenant) to create the AzureDeveloperCLICredential after subscription selection. For multi-tenant/guest users, this differs from Subscription.UserTenantId (the user access tenant), causing 'refresh token expired' errors. This aligns the extension with how azd core resolves credentials via SubscriptionsManager.LookupTenant(), which returns UserAccessTenantId. Fixes Azure#7077 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…7078) The extension was using Subscription.TenantId (the resource tenant) to create the AzureDeveloperCLICredential after subscription selection. For multi-tenant/guest users, this differs from Subscription.UserTenantId (the user access tenant), causing 'refresh token expired' errors. This aligns the extension with how azd core resolves credentials via SubscriptionsManager.LookupTenant(), which returns UserAccessTenantId. Fixes Azure#7077 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…7078) The extension was using Subscription.TenantId (the resource tenant) to create the AzureDeveloperCLICredential after subscription selection. For multi-tenant/guest users, this differs from Subscription.UserTenantId (the user access tenant), causing 'refresh token expired' errors. This aligns the extension with how azd core resolves credentials via SubscriptionsManager.LookupTenant(), which returns UserAccessTenantId. Fixes Azure#7077 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…7078) The extension was using Subscription.TenantId (the resource tenant) to create the AzureDeveloperCLICredential after subscription selection. For multi-tenant/guest users, this differs from Subscription.UserTenantId (the user access tenant), causing 'refresh token expired' errors. This aligns the extension with how azd core resolves credentials via SubscriptionsManager.LookupTenant(), which returns UserAccessTenantId. Fixes Azure#7077 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…7078) The extension was using Subscription.TenantId (the resource tenant) to create the AzureDeveloperCLICredential after subscription selection. For multi-tenant/guest users, this differs from Subscription.UserTenantId (the user access tenant), causing 'refresh token expired' errors. This aligns the extension with how azd core resolves credentials via SubscriptionsManager.LookupTenant(), which returns UserAccessTenantId. Fixes Azure#7077 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Fix
Multiple extensions were using
Subscription.TenantId(the resource tenant — the tenant that owns the subscription) when creatingAzureDeveloperCLICredentialafter user subscription selection.For multi-tenant/guest users,
TenantIddiffers fromUserTenantId(the tenant the user authenticated through). Using the resource tenant causes the credential to target a tenant the user may not have direct auth tokens for, resulting inAADSTS70043/AADSTS700082"refresh token expired" errors.Change
This aligns all extensions with how azd core resolves credentials —
SubscriptionsManager.LookupTenant()returnsUserAccessTenantId, notTenantId.For single-tenant users,
TenantId == UserTenantId, so no behavior change.Affected extensions
Extensions already correct (using
LookupTenant()): azure.appservice, azure.ai.agents (parser.go, service_target_agent.go).Fixes #7077
Related: #7070