Skip to content

Commit 7314166

Browse files
feat: default axure credential
1 parent 1cb9d90 commit 7314166

3 files changed

Lines changed: 93 additions & 13 deletions

File tree

EssentialCSharp.Chat.Shared/EssentialCSharp.Chat.Common.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
</PropertyGroup>
66

77
<ItemGroup>
8+
<PackageReference Include="Azure.Identity" />
89
<PackageReference Include="Microsoft.SemanticKernel" />
910
<PackageReference Include="Microsoft.SemanticKernel.Connectors.PgVector" />
1011
<PackageReference Include="ModelContextProtocol" />

EssentialCSharp.Chat.Shared/Extensions/ServiceCollectionExtensions.cs

Lines changed: 92 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
using Azure.AI.OpenAI;
2+
using Azure.Core;
3+
using Azure.Identity;
24
using EssentialCSharp.Chat.Common.Services;
35
using Microsoft.Extensions.Configuration;
46
using Microsoft.Extensions.DependencyInjection;
@@ -9,38 +11,52 @@ namespace EssentialCSharp.Chat.Common.Extensions;
911
public static class ServiceCollectionExtensions
1012
{
1113
/// <summary>
12-
/// Adds Azure OpenAI and related AI services to the service collection
14+
/// Adds Azure OpenAI and related AI services to the service collection using Managed Identity
1315
/// </summary>
1416
/// <param name="services">The service collection to add services to</param>
1517
/// <param name="aiOptions">The AI configuration options</param>
1618
/// <param name="postgresConnectionString">The PostgreSQL connection string for the vector store</param>
19+
/// <param name="credential">The token credential to use for authentication. If null, DefaultAzureCredential will be used.</param>
1720
/// <returns>The service collection for chaining</returns>
18-
public static IServiceCollection AddAzureOpenAIServices(this IServiceCollection services, AIOptions aiOptions, string postgresConnectionString)
21+
public static IServiceCollection AddAzureOpenAIServices(
22+
this IServiceCollection services,
23+
AIOptions aiOptions,
24+
string postgresConnectionString,
25+
TokenCredential? credential = null)
1926
{
20-
if (string.IsNullOrEmpty(aiOptions.Endpoint) ||
21-
string.IsNullOrEmpty(aiOptions.ApiKey))
22-
// Register Azure OpenAI services
27+
// Use DefaultAzureCredential if no credential is provided
28+
// This works both locally (using Azure CLI, Visual Studio, etc.) and in Azure (using Managed Identity)
29+
credential ??= new DefaultAzureCredential();
30+
31+
if (string.IsNullOrEmpty(aiOptions.Endpoint))
32+
{
33+
throw new InvalidOperationException("AIOptions.Endpoint is required.");
34+
}
35+
36+
var endpoint = new Uri(aiOptions.Endpoint);
37+
38+
// Register Azure OpenAI services with Managed Identity authentication
2339
#pragma warning disable SKEXP0010 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
2440
services.AddAzureOpenAIChatClient(
2541
aiOptions.ChatDeploymentName,
26-
aiOptions.Endpoint,
27-
aiOptions.ApiKey);
42+
endpoint.ToString(),
43+
credential);
2844

2945
services.AddSingleton(provider =>
30-
new AzureOpenAIClient(new Uri(aiOptions.Endpoint), new Azure.AzureKeyCredential(aiOptions.ApiKey)));
46+
new AzureOpenAIClient(endpoint, credential));
3147

3248
services.AddAzureOpenAIChatCompletion(
3349
aiOptions.ChatDeploymentName,
3450
aiOptions.Endpoint,
35-
aiOptions.ApiKey);
51+
credential);
3652

3753
// Add PostgreSQL vector store
3854
services.AddPostgresVectorStore(postgresConnectionString);
3955

4056
services.AddAzureOpenAIEmbeddingGenerator(
4157
aiOptions.VectorGenerationDeploymentName,
4258
aiOptions.Endpoint,
43-
aiOptions.ApiKey);
59+
credential);
4460
#pragma warning restore SKEXP0010
4561

4662
// Register shared AI services
@@ -57,8 +73,12 @@ public static IServiceCollection AddAzureOpenAIServices(this IServiceCollection
5773
/// </summary>
5874
/// <param name="services">The service collection to add services to</param>
5975
/// <param name="configuration">The configuration to read AIOptions from</param>
76+
/// <param name="credential">Optional token credential to use for authentication. If null, DefaultAzureCredential will be used.</param>
6077
/// <returns>The service collection for chaining</returns>
61-
public static IServiceCollection AddAzureOpenAIServices(this IServiceCollection services, IConfiguration configuration)
78+
public static IServiceCollection AddAzureOpenAIServices(
79+
this IServiceCollection services,
80+
IConfiguration configuration,
81+
TokenCredential? credential = null)
6282
{
6383
// Configure AI options from configuration
6484
services.Configure<AIOptions>(configuration.GetSection("AIOptions"));
@@ -73,6 +93,66 @@ public static IServiceCollection AddAzureOpenAIServices(this IServiceCollection
7393
var postgresConnectionString = configuration.GetConnectionString("PostgresVectorStore") ??
7494
throw new InvalidOperationException("Connection string 'PostgresVectorStore' not found.");
7595

76-
return services.AddAzureOpenAIServices(aiOptions, postgresConnectionString);
96+
return services.AddAzureOpenAIServices(aiOptions, postgresConnectionString, credential);
97+
}
98+
99+
/// <summary>
100+
/// Adds Azure OpenAI and related AI services to the service collection using API key authentication (legacy)
101+
/// </summary>
102+
/// <param name="services">The service collection to add services to</param>
103+
/// <param name="aiOptions">The AI configuration options</param>
104+
/// <param name="postgresConnectionString">The PostgreSQL connection string for the vector store</param>
105+
/// <param name="apiKey">The API key for Azure OpenAI authentication</param>
106+
/// <returns>The service collection for chaining</returns>
107+
[Obsolete("API key authentication is not recommended for production. Use AddAzureOpenAIServices with Managed Identity instead.")]
108+
public static IServiceCollection AddAzureOpenAIServicesWithApiKey(
109+
this IServiceCollection services,
110+
AIOptions aiOptions,
111+
string postgresConnectionString,
112+
string apiKey)
113+
{
114+
if (string.IsNullOrEmpty(apiKey))
115+
{
116+
throw new ArgumentException("API key cannot be null or empty.", nameof(apiKey));
117+
}
118+
119+
if (string.IsNullOrEmpty(aiOptions.Endpoint))
120+
{
121+
throw new InvalidOperationException("AIOptions.Endpoint is required.");
122+
}
123+
124+
var endpoint = new Uri(aiOptions.Endpoint);
125+
126+
// Register Azure OpenAI services with API key authentication
127+
#pragma warning disable SKEXP0010 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
128+
services.AddAzureOpenAIChatClient(
129+
aiOptions.ChatDeploymentName,
130+
aiOptions.Endpoint,
131+
apiKey);
132+
133+
services.AddSingleton(provider =>
134+
new AzureOpenAIClient(endpoint, new Azure.AzureKeyCredential(apiKey)));
135+
136+
services.AddAzureOpenAIChatCompletion(
137+
aiOptions.ChatDeploymentName,
138+
aiOptions.Endpoint,
139+
apiKey);
140+
141+
// Add PostgreSQL vector store
142+
services.AddPostgresVectorStore(postgresConnectionString);
143+
144+
services.AddAzureOpenAIEmbeddingGenerator(
145+
aiOptions.VectorGenerationDeploymentName,
146+
aiOptions.Endpoint,
147+
apiKey);
148+
#pragma warning restore SKEXP0010
149+
150+
// Register shared AI services
151+
services.AddSingleton<EmbeddingService>();
152+
services.AddSingleton<AISearchService>();
153+
services.AddSingleton<AIChatService>();
154+
services.AddSingleton<MarkdownChunkingService>();
155+
156+
return services;
77157
}
78158
}

EssentialCSharp.Web/EssentialCSharp.Web.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
</ItemGroup>
1515

1616
<ItemGroup>
17-
<PackageReference Include="Azure.Identity" />
1817
<PackageReference Include="Azure.Monitor.OpenTelemetry.AspNetCore" />
1918
<PackageReference Include="AspNet.Security.OAuth.GitHub" />
2019
<PackageReference Include="EssentialCSharp.Shared.Models" />

0 commit comments

Comments
 (0)