From 5789a261476c23b02f1a788ccf726d6545c7fed2 Mon Sep 17 00:00:00 2001 From: Alex Wolf Date: Mon, 17 Nov 2025 16:55:19 -0500 Subject: [PATCH 01/13] Improve client registration guidance --- docs/azure/sdk/aspnetcore-guidance.md | 2 +- docs/azure/sdk/dependency-injection.md | 11 ++--------- docs/azure/sdk/logging.md | 4 ++-- .../aspnetcore-guidance/BlazorSample/Program.cs | 3 --- .../aspnetcore-guidance/MinApiSample/Program.cs | 2 -- .../authentication/best-practices/CCA/Program.cs | 2 -- .../authentication/credential-chains/Program.cs | 3 --- .../authentication/local-dev-account/Program.cs | 2 -- .../system-assigned-managed-identity/Program.cs | 2 -- .../user-assigned-managed-identity/Program.cs | 6 ------ .../HostApplicationBuilder/Program.cs | 4 ---- .../dependency-injection/HostBuilder/Program.cs | 4 ---- .../WebApplicationBuilder/Program.cs | 4 ---- docs/azure/sdk/snippets/pagination/Program.cs | 1 - 14 files changed, 5 insertions(+), 45 deletions(-) diff --git a/docs/azure/sdk/aspnetcore-guidance.md b/docs/azure/sdk/aspnetcore-guidance.md index 74faccae157d8..5d4a1a884f454 100644 --- a/docs/azure/sdk/aspnetcore-guidance.md +++ b/docs/azure/sdk/aspnetcore-guidance.md @@ -106,7 +106,7 @@ Complete the steps in the following sections to update your app to use JSON file In the preceding JSON sample: - The top-level key names, `KeyVault`, `ServiceBus`, and `Storage`, are arbitrary names used to reference the config sections from your code. You will pass these names to `AddClient` extension methods to configure a given client. All other key names map to specific client options, and JSON serialization is performed in a case-insensitive manner. - - The `KeyVault:VaultUri`, `ServiceBus:Namespace`, and `Storage:ServiceUri` key values map to the arguments of the , , and constructor overloads, respectively. The `TokenCredential` variants of the constructors are used because a default `TokenCredential` is set via the method call. + - The `KeyVault:VaultUri`, `ServiceBus:Namespace`, and `Storage:ServiceUri` key values map to the arguments of the , , and constructor overloads, respectively. 1. Update the the `Program.cs` file to retrieve the JSON file configurations using `IConfiguration` and pass them into your service registrations: diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index e8996ba79bc0b..35eb21d620e94 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -58,7 +58,7 @@ In the *Program.cs* file, invoke the , and , respectively. The `Uri`- and `string`-typed arguments are passed. To avoid specifying these URLs explicitly, see the [Store configuration separately from code](#store-configuration-separately-from-code) section. -* is used to satisfy the `TokenCredential` argument requirement for each registered client. When one of the clients is created, `DefaultAzureCredential` is used to authenticate. +* Each registered client automatically uses for `TokenCredential` unless you explicitly override it (for example, with `WithCredential`). * Service Bus subclients are registered for each queue on the service using the subclient and corresponding options types. The queue names for the subclients are retrieved using a separate method outside of the service registration because the `GetQueuesAsync` method must be run asynchronously. * An Azure OpenAI client is registered using a custom client factory via the method, which provides control over how a client instance is created. Custom client factories are useful in the following cases: * You need to use other dependencies during the client construction. @@ -145,8 +145,6 @@ builder.Services.AddAzureClients(clientBuilder => clientBuilder.AddServiceBusClientWithNamespace( builder.Configuration["ServiceBus:Namespace"]); - clientBuilder.UseCredential(new DefaultAzureCredential()); - // Set up any default settings clientBuilder.ConfigureDefaults( builder.Configuration.GetSection("AzureDefaults")); @@ -167,8 +165,6 @@ builder.Services.AddAzureClients(clientBuilder => clientBuilder.AddServiceBusClientWithNamespace( builder.Configuration["ServiceBus:Namespace"]); - clientBuilder.UseCredential(new DefaultAzureCredential()); - // Set up any default settings clientBuilder.ConfigureDefaults( builder.Configuration.GetSection("AzureDefaults")); @@ -193,8 +189,6 @@ IHost host = Host.CreateDefaultBuilder(args) clientBuilder.AddServiceBusClientWithNamespace( hostContext.Configuration["ServiceBus:Namespace"]); - clientBuilder.UseCredential(new DefaultAzureCredential()); - // Set up any default settings clientBuilder.ConfigureDefaults( hostContext.Configuration.GetSection("AzureDefaults")); @@ -211,7 +205,7 @@ In the preceding JSON sample: * The `AzureDefaults.Retry` object literal: * Represents the [retry policy configuration settings](#configure-a-new-retry-policy). * Corresponds to the property. Within that object literal, you find the `MaxRetries` key, which corresponds to the property. -* The `KeyVault:VaultUri`, `ServiceBus:Namespace`, and `Storage:ServiceUri` key values map to the `Uri`- and `string`-typed arguments of the , , and constructor overloads, respectively. The `TokenCredential` variants of the constructors are used because a default `TokenCredential` is set via the method call. +* The `KeyVault:VaultUri`, `ServiceBus:Namespace`, and `Storage:ServiceUri` key values map to the `Uri`- and `string`-typed arguments of the , , and constructor overloads, respectively. ## Configure multiple service clients with different names @@ -283,7 +277,6 @@ builder.Services.AddAzureClients(clientBuilder => // Establish the global defaults clientBuilder.ConfigureDefaults( builder.Configuration.GetSection("AzureDefaults")); - clientBuilder.UseCredential(new DefaultAzureCredential()); // A Key Vault Secrets client using the global defaults clientBuilder.AddSecretClient( diff --git a/docs/azure/sdk/logging.md b/docs/azure/sdk/logging.md index 794d72af82559..5f3eaee375a08 100644 --- a/docs/azure/sdk/logging.md +++ b/docs/azure/sdk/logging.md @@ -139,7 +139,7 @@ Using the Azure Service Bus library as an example, complete the following steps: { azureBuilder.AddServiceBusClient( builder.Configuration.GetConnectionString("ServiceBus")); - azureBuilder.UseCredential(new DefaultAzureCredential()); + // DefaultAzureCredential is applied automatically. }); ``` @@ -148,7 +148,7 @@ Using the Azure Service Bus library as an example, complete the following steps: - Registers the following objects with the dependency injection (DI) container: - Log forwarder service - Azure Service Bus client - - Sets the default token credential to be used for all registered clients. + - Applies automatically for authentication unless a different credential is explicitly configured. 1. In *appsettings.json*, change the Service Bus library's default log level. For example, toggle it to `Debug` by setting the `Logging:LogLevel:Azure.Messaging.ServiceBus` key as follows: diff --git a/docs/azure/sdk/snippets/aspnetcore-guidance/BlazorSample/Program.cs b/docs/azure/sdk/snippets/aspnetcore-guidance/BlazorSample/Program.cs index cb3a6233e5283..84f566ce100b5 100644 --- a/docs/azure/sdk/snippets/aspnetcore-guidance/BlazorSample/Program.cs +++ b/docs/azure/sdk/snippets/aspnetcore-guidance/BlazorSample/Program.cs @@ -24,9 +24,6 @@ (_, _, provider) => provider.GetService() .CreateSender(queue)).WithName(queue); } - - // Register a shared credential for Microsoft Entra ID authentication - clientBuilder.UseCredential(new DefaultAzureCredential()); }); var app = builder.Build(); diff --git a/docs/azure/sdk/snippets/aspnetcore-guidance/MinApiSample/Program.cs b/docs/azure/sdk/snippets/aspnetcore-guidance/MinApiSample/Program.cs index ac5f9ef751885..c7c89b35f830f 100644 --- a/docs/azure/sdk/snippets/aspnetcore-guidance/MinApiSample/Program.cs +++ b/docs/azure/sdk/snippets/aspnetcore-guidance/MinApiSample/Program.cs @@ -33,8 +33,6 @@ .CreateSender(queue)).WithName(queue); } - clientBuilder.UseCredential(new DefaultAzureCredential()); - // Set up any default settings clientBuilder.ConfigureDefaults( builder.Configuration.GetSection("AzureDefaults")); diff --git a/docs/azure/sdk/snippets/authentication/best-practices/CCA/Program.cs b/docs/azure/sdk/snippets/authentication/best-practices/CCA/Program.cs index cc05915bcc901..d607575ed44be 100644 --- a/docs/azure/sdk/snippets/authentication/best-practices/CCA/Program.cs +++ b/docs/azure/sdk/snippets/authentication/best-practices/CCA/Program.cs @@ -31,8 +31,6 @@ new AzureCliCredential(), new AzurePowerShellCredential()); } - - clientBuilder.UseCredential(credential); }); #endregion snippet_credential_reuse_AspNetCore diff --git a/docs/azure/sdk/snippets/authentication/credential-chains/Program.cs b/docs/azure/sdk/snippets/authentication/credential-chains/Program.cs index 81b83a5efccda..a8d27df03911e 100644 --- a/docs/azure/sdk/snippets/authentication/credential-chains/Program.cs +++ b/docs/azure/sdk/snippets/authentication/credential-chains/Program.cs @@ -26,9 +26,6 @@ new Uri($"https://{keyVaultName}.vault.azure.net")); clientBuilder.AddBlobServiceClient( new Uri($"https://{storageAccountName}.blob.core.windows.net")); - - DefaultAzureCredential credential = new(); - clientBuilder.UseCredential(credential); }); #endregion snippet_Dac diff --git a/docs/azure/sdk/snippets/authentication/local-dev-account/Program.cs b/docs/azure/sdk/snippets/authentication/local-dev-account/Program.cs index b09ccffb4e6aa..715e0ec60b865 100644 --- a/docs/azure/sdk/snippets/authentication/local-dev-account/Program.cs +++ b/docs/azure/sdk/snippets/authentication/local-dev-account/Program.cs @@ -50,8 +50,6 @@ void registerUsingServicePrincipal(WebApplicationBuilder builder) { clientBuilder.AddBlobServiceClient( new Uri("https://.blob.core.windows.net")); - - clientBuilder.UseCredential(new DefaultAzureCredential()); }); #endregion snippet_DefaultAzureCredential_UseCredential diff --git a/docs/azure/sdk/snippets/authentication/system-assigned-managed-identity/Program.cs b/docs/azure/sdk/snippets/authentication/system-assigned-managed-identity/Program.cs index 7ee24b5450ab2..08e0b6e3fa534 100644 --- a/docs/azure/sdk/snippets/authentication/system-assigned-managed-identity/Program.cs +++ b/docs/azure/sdk/snippets/authentication/system-assigned-managed-identity/Program.cs @@ -23,8 +23,6 @@ // Running locally on dev machine - DO NOT use in production or outside of local dev credential = new DefaultAzureCredential(); } - - clientBuilder.UseCredential(credential); }); #endregion snippet_MIC_UseCredential diff --git a/docs/azure/sdk/snippets/authentication/user-assigned-managed-identity/Program.cs b/docs/azure/sdk/snippets/authentication/user-assigned-managed-identity/Program.cs index 3a2211ece4eda..7e62c2d28de40 100644 --- a/docs/azure/sdk/snippets/authentication/user-assigned-managed-identity/Program.cs +++ b/docs/azure/sdk/snippets/authentication/user-assigned-managed-identity/Program.cs @@ -63,8 +63,6 @@ void registerUsingClientId(WebApplicationBuilder builder) // Running locally on dev machine - DO NOT use in production or outside of local dev credential = new DefaultAzureCredential(); } - - clientBuilder.UseCredential(credential); }); #endregion snippet_MIC_ClientId_UseCredential @@ -110,8 +108,6 @@ void registerUsingObjectId(WebApplicationBuilder builder) // Running locally on dev machine - DO NOT use in production or outside of local dev credential = new DefaultAzureCredential(); } - - clientBuilder.UseCredential(credential); }); #endregion snippet_MIC_ObjectId_UseCredential @@ -158,8 +154,6 @@ void registerUsingResourceId(WebApplicationBuilder builder) // Running locally on dev machine - DO NOT use in production or outside of local dev credential = new DefaultAzureCredential(); } - - clientBuilder.UseCredential(credential); }); #endregion snippet_MIC_ResourceId_UseCredential diff --git a/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs index 09df8f2a4b300..b93b9b9d6776a 100644 --- a/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs @@ -14,10 +14,6 @@ clientBuilder.AddSecretClient(new Uri("")); clientBuilder.AddBlobServiceClient(new Uri("")); clientBuilder.AddServiceBusClientWithNamespace(".servicebus.windows.net"); - - // Set a credential for all clients to use by default - DefaultAzureCredential credential = new(); - clientBuilder.UseCredential(credential); // Register subclients for Service Bus List queueNames = await GetQueueNames(credential); diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs index 2c7f1779c115a..209ea3b8482ed 100644 --- a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs @@ -14,10 +14,6 @@ clientBuilder.AddSecretClient(new Uri("")); clientBuilder.AddBlobServiceClient(new Uri("")); clientBuilder.AddServiceBusClientWithNamespace(".servicebus.windows.net"); - - // Set a credential for all clients to use by default - DefaultAzureCredential credential = new(); - clientBuilder.UseCredential(credential); // Register a subclient for each Service Bus Queue List queueNames = await GetQueueNames(credential); diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs index 5e382e2565f8a..a0a830226f988 100644 --- a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs @@ -15,10 +15,6 @@ clientBuilder.AddServiceBusClientWithNamespace( ".servicebus.windows.net"); - // Set a credential for all clients to use by default - DefaultAzureCredential credential = new(); - clientBuilder.UseCredential(credential); - // Register a subclient for each Service Bus Queue List queueNames = await GetQueueNames(credential); foreach (string queue in queueNames) diff --git a/docs/azure/sdk/snippets/pagination/Program.cs b/docs/azure/sdk/snippets/pagination/Program.cs index dca523354fcf5..43b10828a6a59 100644 --- a/docs/azure/sdk/snippets/pagination/Program.cs +++ b/docs/azure/sdk/snippets/pagination/Program.cs @@ -17,7 +17,6 @@ Uri vaultUri = new(Environment.GetEnvironmentVariable("AZURE_KEY_VAULT_URI")!); builder.AddSecretClient(vaultUri); - builder.UseCredential(new DefaultAzureCredential()); }); using IHost host = builder.Build(); From ff11c7646d8305779ac67388fe2609dd912523d6 Mon Sep 17 00:00:00 2001 From: Alex Wolf Date: Mon, 17 Nov 2025 17:19:41 -0500 Subject: [PATCH 02/13] edits --- docs/azure/sdk/logging.md | 1 - .../sdk/snippets/authentication/best-practices/CCA/Program.cs | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/azure/sdk/logging.md b/docs/azure/sdk/logging.md index 5f3eaee375a08..30313d1038b86 100644 --- a/docs/azure/sdk/logging.md +++ b/docs/azure/sdk/logging.md @@ -139,7 +139,6 @@ Using the Azure Service Bus library as an example, complete the following steps: { azureBuilder.AddServiceBusClient( builder.Configuration.GetConnectionString("ServiceBus")); - // DefaultAzureCredential is applied automatically. }); ``` diff --git a/docs/azure/sdk/snippets/authentication/best-practices/CCA/Program.cs b/docs/azure/sdk/snippets/authentication/best-practices/CCA/Program.cs index d607575ed44be..cc05915bcc901 100644 --- a/docs/azure/sdk/snippets/authentication/best-practices/CCA/Program.cs +++ b/docs/azure/sdk/snippets/authentication/best-practices/CCA/Program.cs @@ -31,6 +31,8 @@ new AzureCliCredential(), new AzurePowerShellCredential()); } + + clientBuilder.UseCredential(credential); }); #endregion snippet_credential_reuse_AspNetCore From ab4d0d5039a0380e1285608af3fa0a0fe35e4d4a Mon Sep 17 00:00:00 2001 From: Alex Wolf Date: Mon, 17 Nov 2025 17:51:48 -0500 Subject: [PATCH 03/13] edits --- .../dependency-injection/HostApplicationBuilder/Program.cs | 4 ++++ .../sdk/snippets/dependency-injection/HostBuilder/Program.cs | 4 ++++ .../dependency-injection/WebApplicationBuilder/Program.cs | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs index b93b9b9d6776a..cbe9749d590ea 100644 --- a/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/HostApplicationBuilder/Program.cs @@ -15,6 +15,10 @@ clientBuilder.AddBlobServiceClient(new Uri("")); clientBuilder.AddServiceBusClientWithNamespace(".servicebus.windows.net"); + // Set a credential for all clients to use by default + DefaultAzureCredential credential = new(); + clientBuilder.UseCredential(credential); + // Register subclients for Service Bus List queueNames = await GetQueueNames(credential); foreach (string queueName in queueNames) diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs index 209ea3b8482ed..3c604520a08bd 100644 --- a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs @@ -15,6 +15,10 @@ clientBuilder.AddBlobServiceClient(new Uri("")); clientBuilder.AddServiceBusClientWithNamespace(".servicebus.windows.net"); + // Set a credential for all clients to use by default + DefaultAzureCredential credential = new(); + clientBuilder.UseCredential(credential); + // Register a subclient for each Service Bus Queue List queueNames = await GetQueueNames(credential); foreach (string queue in queueNames) diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs index a0a830226f988..5e382e2565f8a 100644 --- a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs @@ -15,6 +15,10 @@ clientBuilder.AddServiceBusClientWithNamespace( ".servicebus.windows.net"); + // Set a credential for all clients to use by default + DefaultAzureCredential credential = new(); + clientBuilder.UseCredential(credential); + // Register a subclient for each Service Bus Queue List queueNames = await GetQueueNames(credential); foreach (string queue in queueNames) From ebf0774ebf9a8021eec464fcca68fdec61a0502e Mon Sep 17 00:00:00 2001 From: Alex Wolf Date: Mon, 17 Nov 2025 18:26:13 -0500 Subject: [PATCH 04/13] fixes --- docs/azure/sdk/aspnetcore-guidance.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/azure/sdk/aspnetcore-guidance.md b/docs/azure/sdk/aspnetcore-guidance.md index 5d4a1a884f454..315d47a3a46c1 100644 --- a/docs/azure/sdk/aspnetcore-guidance.md +++ b/docs/azure/sdk/aspnetcore-guidance.md @@ -54,7 +54,7 @@ Complete the following steps to register the services you need: ## [Minimal API](#tab/api) - :::code language="csharp" source="snippets/aspnetcore-guidance/MinApiSample/Program.cs" range="52-73" highlight="1-3,6,8,11-12"::: + :::code language="csharp" source="snippets/aspnetcore-guidance/MinApiSample/Program.cs" range="50-71" highlight="1-3,6,8,11-12"::: ## [Blazor](#tab/blazor) @@ -80,9 +80,9 @@ Use the [Azure Identity](/dotnet/api/overview/azure/identity-readme) library for dotnet add package Azure.Identity ``` -1. In the `Program.cs` file of your app, invoke the extension method from the `Microsoft.Extensions.Azure` library to set a shared `DefaultAzureCredential` instance for all registered Azure service clients: +1. In the `Program.cs` file of your app, invoke the extension method from the `Microsoft.Extensions.Azure` library to set a shared `DefaultAzureCredential` instance for all registered Azure service clients: - :::code language="csharp" source="snippets/aspnetcore-guidance/BlazorSample/Program.cs" range="11-30" highlight="19"::: + :::code language="csharp" source="snippets/aspnetcore-guidance/BlazorSample/Program.cs" range="11-30" ::: `DefaultAzureCredential` discovers available credentials in the current environment and uses them to authenticate to Azure services. For the order and locations in which `DefaultAzureCredential` scans for credentials, see [DefaultAzureCredential overview](/dotnet/azure/sdk/authentication/credential-chains?tabs=dac#defaultazurecredential-overview). Using a shared `DefaultAzureCredential` instance ensures the underlying token cache is used, which improves application resilience and performance due to fewer requests for a new token. @@ -122,7 +122,7 @@ You may want to change default Azure client configurations globally or for a spe 2. In the `Program.cs` file, call the `ConfigureDefaults` extension method to retrieve the default settings and apply them to your service clients: - :::code language="csharp" source="snippets/aspnetcore-guidance/MinApiSample/Program.cs" range="14-41" highlight="26-27"::: + :::code language="csharp" source="snippets/aspnetcore-guidance/MinApiSample/Program.cs" range="14-41" highlight="24-25"::: ## Configure logging From c8f81975f7a160995341824a06bc4e913d594abe Mon Sep 17 00:00:00 2001 From: Alex Wolf Date: Mon, 17 Nov 2025 18:31:13 -0500 Subject: [PATCH 05/13] fix --- docs/azure/sdk/dependency-injection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 35eb21d620e94..cdfb300004b3b 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -47,7 +47,7 @@ In the *Program.cs* file, invoke the Date: Mon, 17 Nov 2025 18:33:58 -0500 Subject: [PATCH 06/13] fixes --- docs/azure/sdk/authentication/best-practices.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/azure/sdk/authentication/best-practices.md b/docs/azure/sdk/authentication/best-practices.md index ddbc96675c833..c95c33a977aa1 100644 --- a/docs/azure/sdk/authentication/best-practices.md +++ b/docs/azure/sdk/authentication/best-practices.md @@ -24,9 +24,9 @@ For example, consider the following hypothetical sequence of events: To prevent these types of subtle issues or silent failures in production apps, replace `DefaultAzureCredential` with a specific `TokenCredential` implementation, such as `ManagedIdentityCredential`. See the [**Derived** list](/dotnet/api/azure.core.tokencredential?view=azure-dotnet&preserve-view=true#definition) for options. -For example, consider the following `DefaultAzureCredential` configuration in an ASP.NET Core project: +For example, consider the following configuration in an ASP.NET Core project, which applies `DefaultAzureCredential` to all registered services: -:::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_Dac" highlight="8-9"::: +:::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_Dac" ::: Modify the preceding code to select a credential based on the environment in which the app is running: From 6557acbacfdef4cefaa99e01018cf5800759b53c Mon Sep 17 00:00:00 2001 From: Alex Wolf Date: Tue, 18 Nov 2025 08:49:50 -0500 Subject: [PATCH 07/13] edits --- docs/azure/sdk/authentication/best-practices.md | 2 +- docs/azure/sdk/dependency-injection.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/azure/sdk/authentication/best-practices.md b/docs/azure/sdk/authentication/best-practices.md index c95c33a977aa1..92cbe4d5d353a 100644 --- a/docs/azure/sdk/authentication/best-practices.md +++ b/docs/azure/sdk/authentication/best-practices.md @@ -24,7 +24,7 @@ For example, consider the following hypothetical sequence of events: To prevent these types of subtle issues or silent failures in production apps, replace `DefaultAzureCredential` with a specific `TokenCredential` implementation, such as `ManagedIdentityCredential`. See the [**Derived** list](/dotnet/api/azure.core.tokencredential?view=azure-dotnet&preserve-view=true#definition) for options. -For example, consider the following configuration in an ASP.NET Core project, which applies `DefaultAzureCredential` to all registered services: +For example, consider the following configuration in an ASP.NET Core project, which uses `DefaultAzureCredential` for all registered services: :::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_Dac" ::: diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index cdfb300004b3b..e2893d7844a29 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -58,7 +58,7 @@ In the *Program.cs* file, invoke the , and , respectively. The `Uri`- and `string`-typed arguments are passed. To avoid specifying these URLs explicitly, see the [Store configuration separately from code](#store-configuration-separately-from-code) section. -* Each registered client automatically uses for `TokenCredential` unless you explicitly override it (for example, with `WithCredential`). +* Each registered client automatically uses for `TokenCredential` unless you configure a different type of credential (for example, using `WithCredential`). * Service Bus subclients are registered for each queue on the service using the subclient and corresponding options types. The queue names for the subclients are retrieved using a separate method outside of the service registration because the `GetQueuesAsync` method must be run asynchronously. * An Azure OpenAI client is registered using a custom client factory via the method, which provides control over how a client instance is created. Custom client factories are useful in the following cases: * You need to use other dependencies during the client construction. From f0fa2d3b2eec7d75e117605939b79189d40bffa1 Mon Sep 17 00:00:00 2001 From: Alex Wolf Date: Fri, 21 Nov 2025 13:29:35 -0500 Subject: [PATCH 08/13] Fix reuse --- docs/azure/sdk/dependency-injection.md | 6 ++--- .../HostApplicationBuilder/Program.cs | 22 +++++++++-------- .../HostBuilder/Program.cs | 23 +++++++++++------- .../WebApplicationBuilder/Program.cs | 24 +++++++++++-------- 4 files changed, 43 insertions(+), 32 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index e2893d7844a29..37e6bdd9720d2 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -43,15 +43,15 @@ In the *Program.cs* file, invoke the ")); clientBuilder.AddBlobServiceClient(new Uri("")); clientBuilder.AddServiceBusClientWithNamespace(".servicebus.windows.net"); - - // Set a credential for all clients to use by default + + // AddAzureClients implicitly creates a DefaultAzureCredential instance + // Create a credential manually to override the type or access it explicitly for DI registrations + // This example shows credential reuse for GetQueueNames and AddClient calls downstream DefaultAzureCredential credential = new(); clientBuilder.UseCredential(credential); - // Register subclients for Service Bus + // Register a subclient for each Service Bus Queue List queueNames = await GetQueueNames(credential); foreach (string queueName in queueNames) { clientBuilder.AddClient((_, _, provider) => - provider.GetService(typeof(ServiceBusClient)) switch - { - ServiceBusClient client => client.CreateSender(queueName), - _ => throw new InvalidOperationException("Unable to create ServiceBusClient") - }).WithName(queueName); + provider.GetService(typeof(ServiceBusClient)) switch + { + ServiceBusClient client => client.CreateSender(queueName), + _ => throw new InvalidOperationException("Unable to create ServiceBusClient") + }).WithName(queueName); } // Register a custom client factory clientBuilder.AddClient( - (options, _, _) => new AzureOpenAIClient( - new Uri(""), credential, options)); + (options, credential, _) => new AzureOpenAIClient( + new Uri(""), credential, options)); }); }).Build(); diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs index 3c604520a08bd..d4e1633050ca9 100644 --- a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs @@ -14,24 +14,29 @@ clientBuilder.AddSecretClient(new Uri("")); clientBuilder.AddBlobServiceClient(new Uri("")); clientBuilder.AddServiceBusClientWithNamespace(".servicebus.windows.net"); - - // Set a credential for all clients to use by default + + // AddAzureClients implicitly creates a DefaultAzureCredential instance + // Create a credential manually to override the type or access it explicitly for DI registrations + // This example shows credential reuse for GetQueueNames and AddClient calls downstream DefaultAzureCredential credential = new(); clientBuilder.UseCredential(credential); - + // Register a subclient for each Service Bus Queue List queueNames = await GetQueueNames(credential); - foreach (string queue in queueNames) + foreach (string queueName in queueNames) { clientBuilder.AddClient((_, _, provider) => - provider.GetService().CreateSender(queue) - ).WithName(queue); + provider.GetService(typeof(ServiceBusClient)) switch + { + ServiceBusClient client => client.CreateSender(queueName), + _ => throw new InvalidOperationException("Unable to create ServiceBusClient") + }).WithName(queueName); } // Register a custom client factory clientBuilder.AddClient( - (options, _, _) => new AzureOpenAIClient( - new Uri(""), credential, options)); + (options, credential, _) => new AzureOpenAIClient( + new Uri(""), credential, options)); }); }).Build(); @@ -41,7 +46,7 @@ async Task> GetQueueNames(DefaultAzureCredential credential) { // Query the available queues for the Service Bus namespace. var adminClient = new ServiceBusAdministrationClient - (".servicebus.windows.net", credential); + (".servicebus.windows.net"); var queueNames = new List(); // Because the result is async, the queue names need to be captured diff --git a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs index 5e382e2565f8a..3b1344498956e 100644 --- a/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/WebApplicationBuilder/Program.cs @@ -12,26 +12,30 @@ // Register clients for each service clientBuilder.AddSecretClient(new Uri("")); clientBuilder.AddBlobServiceClient(new Uri("")); - clientBuilder.AddServiceBusClientWithNamespace( - ".servicebus.windows.net"); - - // Set a credential for all clients to use by default + clientBuilder.AddServiceBusClientWithNamespace(".servicebus.windows.net"); + + // AddAzureClients implicitly creates a DefaultAzureCredential instance + // Create a credential manually to override the type or access it explicitly for DI registrations + // This example shows credential reuse for GetQueueNames and AddClient calls downstream DefaultAzureCredential credential = new(); clientBuilder.UseCredential(credential); // Register a subclient for each Service Bus Queue List queueNames = await GetQueueNames(credential); - foreach (string queue in queueNames) + foreach (string queueName in queueNames) { - clientBuilder.AddClient( - (_, _, provider) => provider.GetService() - .CreateSender(queue)).WithName(queue); + clientBuilder.AddClient((_, _, provider) => + provider.GetService(typeof(ServiceBusClient)) switch + { + ServiceBusClient client => client.CreateSender(queueName), + _ => throw new InvalidOperationException("Unable to create ServiceBusClient") + }).WithName(queueName); } // Register a custom client factory clientBuilder.AddClient( - (options, _, _) => new AzureOpenAIClient( - new Uri(""), credential, options)); + (options, credential, _) => new AzureOpenAIClient( + new Uri(""), credential, options)); }); WebApplication app = builder.Build(); From df3c67074c31bea35c9ec3dd5a15b26486251aaa Mon Sep 17 00:00:00 2001 From: Alex Wolf Date: Fri, 21 Nov 2025 13:33:11 -0500 Subject: [PATCH 09/13] Fix --- .../sdk/snippets/dependency-injection/HostBuilder/Program.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs index d4e1633050ca9..ce26641172c91 100644 --- a/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs +++ b/docs/azure/sdk/snippets/dependency-injection/HostBuilder/Program.cs @@ -46,7 +46,7 @@ async Task> GetQueueNames(DefaultAzureCredential credential) { // Query the available queues for the Service Bus namespace. var adminClient = new ServiceBusAdministrationClient - (".servicebus.windows.net"); + (".servicebus.windows.net", credential); var queueNames = new List(); // Because the result is async, the queue names need to be captured From 40f0e6267d3972b79dfcdbf34cb8657c25f9b841 Mon Sep 17 00:00:00 2001 From: Alex Wolf Date: Fri, 21 Nov 2025 13:38:25 -0500 Subject: [PATCH 10/13] fix --- docs/azure/sdk/dependency-injection.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 37e6bdd9720d2..56ff5d70d1632 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -43,7 +43,7 @@ In the *Program.cs* file, invoke the Date: Fri, 21 Nov 2025 13:57:42 -0500 Subject: [PATCH 11/13] Fix highlight --- docs/azure/sdk/dependency-injection.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/azure/sdk/dependency-injection.md b/docs/azure/sdk/dependency-injection.md index 56ff5d70d1632..22a869fa22167 100644 --- a/docs/azure/sdk/dependency-injection.md +++ b/docs/azure/sdk/dependency-injection.md @@ -51,7 +51,7 @@ In the *Program.cs* file, invoke the Date: Fri, 21 Nov 2025 14:17:19 -0500 Subject: [PATCH 12/13] Apply suggestions from code review Co-authored-by: Scott Addie <10702007+scottaddie@users.noreply.github.com> --- docs/azure/sdk/authentication/best-practices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/azure/sdk/authentication/best-practices.md b/docs/azure/sdk/authentication/best-practices.md index 92cbe4d5d353a..2e2c14fa5a8a8 100644 --- a/docs/azure/sdk/authentication/best-practices.md +++ b/docs/azure/sdk/authentication/best-practices.md @@ -24,7 +24,7 @@ For example, consider the following hypothetical sequence of events: To prevent these types of subtle issues or silent failures in production apps, replace `DefaultAzureCredential` with a specific `TokenCredential` implementation, such as `ManagedIdentityCredential`. See the [**Derived** list](/dotnet/api/azure.core.tokencredential?view=azure-dotnet&preserve-view=true#definition) for options. -For example, consider the following configuration in an ASP.NET Core project, which uses `DefaultAzureCredential` for all registered services: +For example, consider the following configuration in an ASP.NET Core project. An instance of `DefaultAzureCredential` is implicitly created and used for all registered services: :::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_Dac" ::: From ad64a7c6ce4d828f1b38d76d90a2cb8e2c7db639 Mon Sep 17 00:00:00 2001 From: alexwolfmsft <93200798+alexwolfmsft@users.noreply.github.com> Date: Fri, 21 Nov 2025 14:27:42 -0500 Subject: [PATCH 13/13] Apply suggestions from code review Co-authored-by: Scott Addie <10702007+scottaddie@users.noreply.github.com> --- docs/azure/sdk/authentication/best-practices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/azure/sdk/authentication/best-practices.md b/docs/azure/sdk/authentication/best-practices.md index 2e2c14fa5a8a8..15b889fd623ff 100644 --- a/docs/azure/sdk/authentication/best-practices.md +++ b/docs/azure/sdk/authentication/best-practices.md @@ -24,7 +24,7 @@ For example, consider the following hypothetical sequence of events: To prevent these types of subtle issues or silent failures in production apps, replace `DefaultAzureCredential` with a specific `TokenCredential` implementation, such as `ManagedIdentityCredential`. See the [**Derived** list](/dotnet/api/azure.core.tokencredential?view=azure-dotnet&preserve-view=true#definition) for options. -For example, consider the following configuration in an ASP.NET Core project. An instance of `DefaultAzureCredential` is implicitly created and used for all registered services: +For example, consider the following configuration in an ASP.NET Core project. An instance of `DefaultAzureCredential` is implicitly created and used for all registered service clients: :::code language="csharp" source="../snippets/authentication/credential-chains/Program.cs" id="snippet_Dac" :::