Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions docs/azure/sdk/aspnetcore-guidance.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Complete the following steps to register the services you need:
<!-- markdownlint-disable MD023 -->
## [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":::

<!-- markdownlint-disable MD023 -->
## [Blazor](#tab/blazor)
Expand All @@ -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 <xref:Microsoft.Extensions.Azure.AzureClientFactoryBuilder.UseCredential%2A> 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 <xref:Microsoft.Extensions.Azure.AzureClientServiceCollectionExtensions.AddAzureClients%2A> 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.

Expand All @@ -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 <xref:Azure.Security.KeyVault.Secrets.SecretClient.%23ctor(System.Uri,Azure.Core.TokenCredential,Azure.Security.KeyVault.Secrets.SecretClientOptions)?displayProperty=name>, <xref:Azure.Messaging.ServiceBus.ServiceBusClient.%23ctor(System.String)?displayProperty=name>, and <xref:Azure.Storage.Blobs.BlobServiceClient.%23ctor(System.Uri,Azure.Core.TokenCredential,Azure.Storage.Blobs.BlobClientOptions)?displayProperty=name> constructor overloads, respectively. The `TokenCredential` variants of the constructors are used because a default `TokenCredential` is set via the <xref:Microsoft.Extensions.Azure.AzureClientFactoryBuilder.UseCredential(Azure.Core.TokenCredential)?displayProperty=name> method call.
- The `KeyVault:VaultUri`, `ServiceBus:Namespace`, and `Storage:ServiceUri` key values map to the arguments of the <xref:Azure.Security.KeyVault.Secrets.SecretClient.%23ctor(System.Uri,Azure.Core.TokenCredential,Azure.Security.KeyVault.Secrets.SecretClientOptions)?displayProperty=name>, <xref:Azure.Messaging.ServiceBus.ServiceBusClient.%23ctor(System.String)?displayProperty=name>, and <xref:Azure.Storage.Blobs.BlobServiceClient.%23ctor(System.Uri,Azure.Core.TokenCredential,Azure.Storage.Blobs.BlobClientOptions)?displayProperty=name> 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:

Expand All @@ -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

Expand Down
4 changes: 2 additions & 2 deletions docs/azure/sdk/authentication/best-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -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. 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" 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:

Expand Down
17 changes: 5 additions & 12 deletions docs/azure/sdk/dependency-injection.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,22 @@ In the *Program.cs* file, invoke the <xref:Microsoft.Extensions.Azure.AzureClien

### [WebApplicationBuilder](#tab/web-app-builder)

:::code language="csharp" source="snippets/dependency-injection/WebApplicationBuilder/Program.cs" id="snippet_WebApplicationBuilder" highlight="9-34":::
:::code language="csharp" source="snippets/dependency-injection/WebApplicationBuilder/Program.cs" id="snippet_WebApplicationBuilder" highlight="9-39":::

### [HostApplicationBuilder](#tab/host-app-builder)

:::code language="csharp" source="snippets/dependency-injection/HostApplicationBuilder/Program.cs" highlight="12-39":::
:::code language="csharp" source="snippets/dependency-injection/HostApplicationBuilder/Program.cs" highlight="11-40":::

### [HostBuilder](#tab/host-builder)

:::code language="csharp" source="snippets/dependency-injection/HostBuilder/Program.cs" id="snippet_HostBuilder" highlight="10-34":::
:::code language="csharp" source="snippets/dependency-injection/HostBuilder/Program.cs" id="snippet_HostBuilder" highlight="10-39":::

---

In the preceding code:

* Key Vault Secrets, Blob Storage, and Service Bus clients are registered using the <xref:Microsoft.Extensions.Azure.SecretClientBuilderExtensions.AddSecretClient%2A>, <xref:Microsoft.Extensions.Azure.BlobClientBuilderExtensions.AddBlobServiceClient%2A> and <xref:Microsoft.Extensions.Azure.ServiceBusClientBuilderExtensions.AddServiceBusClientWithNamespace%2A>, 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.
* <xref:Azure.Identity.DefaultAzureCredential> 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 <xref:Azure.Identity.DefaultAzureCredential> 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 <xref:Microsoft.Extensions.Azure.AzureClientFactoryBuilder.AddClient%2A> 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.
Expand Down Expand Up @@ -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"));
Expand All @@ -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"));
Expand All @@ -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"));
Expand All @@ -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 <xref:Azure.Core.ClientOptions.Retry> property. Within that object literal, you find the `MaxRetries` key, which corresponds to the <xref:Azure.Core.RetryOptions.MaxRetries> property.
* The `KeyVault:VaultUri`, `ServiceBus:Namespace`, and `Storage:ServiceUri` key values map to the `Uri`- and `string`-typed arguments of the <xref:Azure.Security.KeyVault.Secrets.SecretClient.%23ctor(System.Uri,Azure.Core.TokenCredential,Azure.Security.KeyVault.Secrets.SecretClientOptions)?displayProperty=fullName>, <xref:Azure.Messaging.ServiceBus.ServiceBusClient.%23ctor(System.String)?displayProperty=fullName>, and <xref:Azure.Storage.Blobs.BlobServiceClient.%23ctor(System.Uri,Azure.Core.TokenCredential,Azure.Storage.Blobs.BlobClientOptions)?displayProperty=fullName> constructor overloads, respectively. The `TokenCredential` variants of the constructors are used because a default `TokenCredential` is set via the <xref:Microsoft.Extensions.Azure.AzureClientFactoryBuilder.UseCredential(Azure.Core.TokenCredential)?displayProperty=fullName> method call.
* The `KeyVault:VaultUri`, `ServiceBus:Namespace`, and `Storage:ServiceUri` key values map to the `Uri`- and `string`-typed arguments of the <xref:Azure.Security.KeyVault.Secrets.SecretClient.%23ctor(System.Uri,Azure.Core.TokenCredential,Azure.Security.KeyVault.Secrets.SecretClientOptions)?displayProperty=fullName>, <xref:Azure.Messaging.ServiceBus.ServiceBusClient.%23ctor(System.String)?displayProperty=fullName>, and <xref:Azure.Storage.Blobs.BlobServiceClient.%23ctor(System.Uri,Azure.Core.TokenCredential,Azure.Storage.Blobs.BlobClientOptions)?displayProperty=fullName> constructor overloads, respectively.

## Configure multiple service clients with different names

Expand Down Expand Up @@ -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(
Expand Down
3 changes: 1 addition & 2 deletions docs/azure/sdk/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,6 @@ Using the Azure Service Bus library as an example, complete the following steps:
{
azureBuilder.AddServiceBusClient(
builder.Configuration.GetConnectionString("ServiceBus"));
azureBuilder.UseCredential(new DefaultAzureCredential());
});
```

Expand All @@ -148,7 +147,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 <xref:Azure.Identity.DefaultAzureCredential> 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:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@
(_, _, provider) => provider.GetService<ServiceBusClient>()
.CreateSender(queue)).WithName(queue);
}

// Register a shared credential for Microsoft Entra ID authentication
clientBuilder.UseCredential(new DefaultAzureCredential());
});

var app = builder.Build();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@
.CreateSender(queue)).WithName(queue);
}

clientBuilder.UseCredential(new DefaultAzureCredential());

// Set up any default settings
clientBuilder.ConfigureDefaults(
builder.Configuration.GetSection("AzureDefaults"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ void registerUsingServicePrincipal(WebApplicationBuilder builder)
{
clientBuilder.AddBlobServiceClient(
new Uri("https://<account-name>.blob.core.windows.net"));

clientBuilder.UseCredential(new DefaultAzureCredential());
});
#endregion snippet_DefaultAzureCredential_UseCredential

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,28 @@
clientBuilder.AddBlobServiceClient(new Uri("<storage_url>"));
clientBuilder.AddServiceBusClientWithNamespace("<your_namespace>.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<string> queueNames = await GetQueueNames(credential);
foreach (string queueName in queueNames)
{
clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>((_, _, 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<AzureOpenAIClient, AzureOpenAIClientOptions>(
(options, _, _) => new AzureOpenAIClient(
new Uri("<url_here>"), credential, options));
(options, credential, _) => new AzureOpenAIClient(
new Uri("<url_here>"), credential, options));
});
}).Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,23 +15,28 @@
clientBuilder.AddBlobServiceClient(new Uri("<storage_url>"));
clientBuilder.AddServiceBusClientWithNamespace("<your_namespace>.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<string> queueNames = await GetQueueNames(credential);
foreach (string queue in queueNames)
foreach (string queueName in queueNames)
{
clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>((_, _, provider) =>
provider.GetService<ServiceBusClient>().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<AzureOpenAIClient, AzureOpenAIClientOptions>(
(options, _, _) => new AzureOpenAIClient(
new Uri("<url_here>"), credential, options));
(options, credential, _) => new AzureOpenAIClient(
new Uri("<url_here>"), credential, options));
});
}).Build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,26 +12,30 @@
// Register clients for each service
clientBuilder.AddSecretClient(new Uri("<key_vault_url>"));
clientBuilder.AddBlobServiceClient(new Uri("<storage_url>"));
clientBuilder.AddServiceBusClientWithNamespace(
"<your_namespace>.servicebus.windows.net");

// Set a credential for all clients to use by default
clientBuilder.AddServiceBusClientWithNamespace("<your_namespace>.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<string> queueNames = await GetQueueNames(credential);
foreach (string queue in queueNames)
foreach (string queueName in queueNames)
{
clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>(
(_, _, provider) => provider.GetService<ServiceBusClient>()
.CreateSender(queue)).WithName(queue);
clientBuilder.AddClient<ServiceBusSender, ServiceBusClientOptions>((_, _, 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<AzureOpenAIClient, AzureOpenAIClientOptions>(
(options, _, _) => new AzureOpenAIClient(
new Uri("<url_here>"), credential, options));
(options, credential, _) => new AzureOpenAIClient(
new Uri("<url_here>"), credential, options));
});

WebApplication app = builder.Build();
Expand Down
Loading