|
| 1 | +--- |
| 2 | +title: "Breaking change - DefaultAzureCredential defaults to ManagedIdentityCredential on ACA and App Service" |
| 3 | +description: "Learn about the breaking change in Aspire 13.0 where DefaultAzureCredential behavior is changed to only use ManagedIdentityCredential when deploying to Azure Container Apps and Azure App Service." |
| 4 | +ms.date: 10/17/2025 |
| 5 | +ai-usage: ai-assisted |
| 6 | +ms.custom: https://github.com/dotnet/docs-aspire/issues/5154 |
| 7 | +--- |
| 8 | + |
| 9 | +# DefaultAzureCredential defaults to ManagedIdentityCredential on ACA and App Service |
| 10 | + |
| 11 | +In Aspire 13.0, when deploying to Azure Container Apps and Azure App Service, the default behavior of `DefaultAzureCredential` has been changed to only use `ManagedIdentityCredential`. This is accomplished by setting the `AZURE_TOKEN_CREDENTIALS` environment variable to ensure deterministic credential resolution. |
| 12 | + |
| 13 | +## Version introduced |
| 14 | + |
| 15 | +Aspire 13.0 |
| 16 | + |
| 17 | +## Previous behavior |
| 18 | + |
| 19 | +Previously, `DefaultAzureCredential` used the full chain of identity providers by default. This meant that `EnvironmentCredential` and `WorkloadIdentityCredential` would be attempted before `ManagedIdentityCredential` when authenticating to Azure resources. |
| 20 | + |
| 21 | +```csharp |
| 22 | +// No explicit environment variable was set |
| 23 | +// DefaultAzureCredential would try credentials in this order: |
| 24 | +// 1. EnvironmentCredential |
| 25 | +// 2. WorkloadIdentityCredential |
| 26 | +// 3. ManagedIdentityCredential |
| 27 | +// ... and others |
| 28 | +``` |
| 29 | + |
| 30 | +## New behavior |
| 31 | + |
| 32 | +Now `DefaultAzureCredential` only uses `ManagedIdentityCredential` when deploying to Azure Container Apps and Azure App Service. This is achieved by setting the `AZURE_TOKEN_CREDENTIALS` environment variable automatically. |
| 33 | + |
| 34 | +```csharp |
| 35 | +// The AZURE_TOKEN_CREDENTIALS environment variable is automatically set |
| 36 | +// DefaultAzureCredential now only uses ManagedIdentityCredential |
| 37 | +``` |
| 38 | + |
| 39 | +This change forces `DefaultAzureCredential` to behave in a deterministic manner and optimizes the underlying `ManagedIdentityCredential` for resilience. |
| 40 | + |
| 41 | +## Type of breaking change |
| 42 | + |
| 43 | +This is a [behavioral change](../categories.md#behavioral-change). |
| 44 | + |
| 45 | +## Reason for change |
| 46 | + |
| 47 | +This change enforces Azure SDK best practices for production environments. Using deterministic credentials improves both security and reliability by: |
| 48 | + |
| 49 | +- Ensuring predictable authentication behavior |
| 50 | +- Reducing potential authentication failures from trying multiple credential types |
| 51 | +- Optimizing credential acquisition performance |
| 52 | +- Following the principle of least privilege by using managed identities |
| 53 | + |
| 54 | +For more information, see: |
| 55 | + |
| 56 | +- [Use deterministic credentials in production environments](https://learn.microsoft.com/dotnet/azure/sdk/authentication/best-practices?tabs=aspdotnet#use-deterministic-credentials-in-production-environments) |
| 57 | +- [GitHub PR dotnet/aspire#11832](https://github.com/dotnet/aspire/pull/11832) |
| 58 | +- [Azure SDK resilience improvements](https://github.com/Azure/azure-sdk-for-net/pull/52545) |
| 59 | + |
| 60 | +## Recommended action |
| 61 | + |
| 62 | +If you were relying on `EnvironmentCredential` or `WorkloadIdentityCredential` in your application, you can choose one of the following options to revert to the old behavior or adapt your code: |
| 63 | + |
| 64 | +### Option 1: Use specific credential types explicitly |
| 65 | + |
| 66 | +Don't use `DefaultAzureCredential` in your application. Instead, explicitly use `EnvironmentCredential` or `WorkloadIdentityCredential` in production code. |
| 67 | + |
| 68 | +### Option 2: Remove the environment variable in your deployment |
| 69 | + |
| 70 | +Implement a `PublishAsAzureContainerApp` callback and remove the environment variable from the bicep: |
| 71 | + |
| 72 | +```csharp |
| 73 | +builder.AddProject<Projects.Frontend>("frontend") |
| 74 | + .PublishAsAzureContainerApp((infra, app) => |
| 75 | + { |
| 76 | + // Remove the AZURE_TOKEN_CREDENTIALS env var to restore previous behavior |
| 77 | + var containerAppContainer = app.Template.Containers[0].Value!; |
| 78 | + var azureTokenCredentialEnv = containerAppContainer.Env |
| 79 | + .Single(v => v.Value!.Name.Value == "AZURE_TOKEN_CREDENTIALS"); |
| 80 | + containerAppContainer.Env.Remove(azureTokenCredentialEnv); |
| 81 | + }); |
| 82 | +``` |
| 83 | + |
| 84 | +For Azure App Service, use a similar approach with `PublishAsAzureAppService`: |
| 85 | + |
| 86 | +```csharp |
| 87 | +builder.AddProject<Projects.Frontend>("frontend") |
| 88 | + .PublishAsAzureAppService((infra, app) => |
| 89 | + { |
| 90 | + // Remove the AZURE_TOKEN_CREDENTIALS env var to restore previous behavior |
| 91 | + var settings = app.Properties.SiteConfig.Value!.AppSettings!; |
| 92 | + var azureTokenCredentialSetting = settings |
| 93 | + .Single(s => s.Value!.Name.Value == "AZURE_TOKEN_CREDENTIALS"); |
| 94 | + settings.Remove(azureTokenCredentialSetting); |
| 95 | + }); |
| 96 | +``` |
| 97 | + |
| 98 | +## Affected APIs |
| 99 | + |
| 100 | +- <xref:Aspire.Hosting.Azure.AzureContainerAppExtensions.AddAzureContainerAppEnvironment*?displayProperty=fullName> |
| 101 | +- <xref:Aspire.Hosting.Azure.AzureAppServiceEnvironmentExtensions.AddAzureAppServiceEnvironment*?displayProperty=fullName> |
0 commit comments