diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommand.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommand.cs index 24fc6cf9..228669b8 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommand.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/PublishCommand.cs @@ -1,20 +1,20 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System.CommandLine; -using Microsoft.Extensions.Logging; -using Microsoft.Agents.A365.DevTools.Cli.Services; +using Microsoft.Agents.A365.DevTools.Cli.Constants; +using Microsoft.Agents.A365.DevTools.Cli.Exceptions; +using Microsoft.Agents.A365.DevTools.Cli.Helpers; using Microsoft.Agents.A365.DevTools.Cli.Models; -using System.Text.Json; -using System.Text.Json.Nodes; -using System.Reflection; -using System.Net.Http.Headers; -using System.IO.Compression; +using Microsoft.Agents.A365.DevTools.Cli.Services; using Microsoft.Agents.A365.DevTools.Cli.Services.Helpers; -using Microsoft.Agents.A365.DevTools.Cli.Helpers; -using Microsoft.Agents.A365.DevTools.Cli.Exceptions; -using Microsoft.Agents.A365.DevTools.Cli.Constants; +using Microsoft.Agents.A365.DevTools.Cli.Services.Internal; +using Microsoft.Extensions.Logging; using Microsoft.Identity.Client; +using System.CommandLine; +using System.IO.Compression; +using System.Net.Http.Headers; +using System.Text.Json; +using System.Text.Json.Nodes; namespace Microsoft.Agents.A365.DevTools.Cli.Commands; @@ -394,10 +394,8 @@ public static Command CreateCommand( logger.LogError("Unable to acquire MOS token. Aborting publish."); return; } - - using var http = new HttpClient(); - http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", mosToken); - http.DefaultRequestHeaders.UserAgent.ParseAdd($"Agent365Publish/{Assembly.GetExecutingAssembly().GetName().Version}"); + + using var http = HttpClientFactory.CreateAuthenticatedClient(mosToken); // Log token info for debugging (first/last chars only for security) if (mosToken.Length >= 20) diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/SetupSubcommands/BlueprintSubcommand.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/SetupSubcommands/BlueprintSubcommand.cs index 33fe89e0..60baa3be 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Commands/SetupSubcommands/BlueprintSubcommand.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Commands/SetupSubcommands/BlueprintSubcommand.cs @@ -8,15 +8,14 @@ using Microsoft.Agents.A365.DevTools.Cli.Helpers; using Microsoft.Agents.A365.DevTools.Cli.Services; using Microsoft.Agents.A365.DevTools.Cli.Services.Helpers; +using Microsoft.Agents.A365.DevTools.Cli.Services.Internal; using Microsoft.Extensions.Logging; using Microsoft.Graph; using System.CommandLine; -using System.Net.Http.Headers; using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text.Json; using System.Text.Json.Nodes; -using System.Threading; namespace Microsoft.Agents.A365.DevTools.Cli.Commands.SetupSubcommands; @@ -574,8 +573,6 @@ public static async Task EnsureDelegatedConsentWithRetriesAsync( }; } - // Create the application using Microsoft Graph SDK - using var httpClient = new HttpClient(); var graphToken = await GetTokenFromGraphClient(logger, graphClient, tenantId, setupConfig.ClientAppId); if (string.IsNullOrEmpty(graphToken)) { @@ -583,7 +580,8 @@ public static async Task EnsureDelegatedConsentWithRetriesAsync( return (false, null, null, null); } - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphToken); + // Create the application using Microsoft Graph SDK + using var httpClient = HttpClientFactory.CreateAuthenticatedClient(graphToken); httpClient.DefaultRequestHeaders.Add("ConsistencyLevel", "eventual"); httpClient.DefaultRequestHeaders.Add("OData-Version", "4.0"); // Required for @odata.type @@ -998,8 +996,7 @@ public static async Task CreateBlueprintClientSecretAsync( throw new InvalidOperationException("Cannot create client secret without Graph API token"); } - using var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphToken); + using var httpClient = HttpClientFactory.CreateAuthenticatedClient(graphToken); var secretBody = new JsonObject { @@ -1175,8 +1172,7 @@ private static async Task CreateFederatedIdentityCredentialAsync( ["audiences"] = new JsonArray { "api://AzureADTokenExchange" } }; - using var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphToken); + using var httpClient = HttpClientFactory.CreateAuthenticatedClient(graphToken); httpClient.DefaultRequestHeaders.Add("ConsistencyLevel", "eventual"); var urls = new [] diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Services/A365CreateInstanceRunner.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Services/A365CreateInstanceRunner.cs index 5a05b3f8..e73e5fcf 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Services/A365CreateInstanceRunner.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Services/A365CreateInstanceRunner.cs @@ -1,14 +1,14 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System.Text.Json; -using System.Text.Json.Nodes; -using Microsoft.Extensions.Logging; -using System.Net.Http.Headers; -using System.Security.Cryptography; -using System.Runtime.InteropServices; using Microsoft.Agents.A365.DevTools.Cli.Constants; using Microsoft.Agents.A365.DevTools.Cli.Services.Helpers; +using Microsoft.Agents.A365.DevTools.Cli.Services.Internal; +using Microsoft.Extensions.Logging; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +using System.Text.Json; +using System.Text.Json.Nodes; namespace Microsoft.Agents.A365.DevTools.Cli.Services; @@ -472,8 +472,7 @@ string GetConfig(string name) => return (false, null); } - using var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); + using var httpClient = HttpClientFactory.CreateAuthenticatedClient(accessToken); // Get current user for sponsor (optional - use delegated token for this) string? currentUserId = null; @@ -483,9 +482,8 @@ string GetConfig(string name) => var delegatedToken = await _graphService.GetGraphAccessTokenAsync(tenantId, ct); if (!string.IsNullOrWhiteSpace(delegatedToken)) { - using var delegatedClient = new HttpClient(); - delegatedClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", delegatedToken); - + using var delegatedClient = HttpClientFactory.CreateAuthenticatedClient(delegatedToken); + var meResponse = await delegatedClient.GetAsync("https://graph.microsoft.com/v1.0/me", ct); if (meResponse.IsSuccessStatusCode) { @@ -599,8 +597,8 @@ string GetConfig(string name) => try { _logger.LogInformation("Acquiring access token using client credentials..."); - - using var httpClient = new HttpClient(); + + using var httpClient = HttpClientFactory.CreateAuthenticatedClient(); var tokenEndpoint = $"https://login.microsoftonline.com/{tenantId}/oauth2/v2.0/token"; var requestBody = new FormUrlEncodedContent(new[] @@ -676,8 +674,7 @@ string GetConfig(string name) => return (false, null); } - using var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphToken); + using var httpClient = HttpClientFactory.CreateAuthenticatedClient(graphToken); // Check if user already exists try @@ -769,8 +766,7 @@ private async Task AssignManagerAsync( { _logger.LogInformation(" - Assigning manager"); - using var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphToken); + using var httpClient = HttpClientFactory.CreateAuthenticatedClient(graphToken); // Look up manager by email var managerUrl = $"https://graph.microsoft.com/v1.0/users?$filter=mail eq '{managerEmail}'"; @@ -934,8 +930,7 @@ private async Task AssignLicensesAsync( return; } - using var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphToken); + using var httpClient = HttpClientFactory.CreateAuthenticatedClient(graphToken); // Set usage location if provided if (!string.IsNullOrWhiteSpace(usageLocation)) @@ -1161,8 +1156,7 @@ private async Task VerifyServicePrincipalExistsAsync( return false; } - using var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphToken); + using var httpClient = HttpClientFactory.CreateAuthenticatedClient(graphToken); // Query for service principal by appId var spUrl = $"https://graph.microsoft.com/v1.0/servicePrincipals?$filter=appId eq '{appId}'"; diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Services/DelegatedConsentService.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Services/DelegatedConsentService.cs index 229d29b1..d02ad72e 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Services/DelegatedConsentService.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Services/DelegatedConsentService.cs @@ -1,11 +1,12 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System.Net.Http.Headers; -using System.Text.Json; using Microsoft.Agents.A365.DevTools.Cli.Constants; using Microsoft.Agents.A365.DevTools.Cli.Services.Helpers; +using Microsoft.Agents.A365.DevTools.Cli.Services.Internal; using Microsoft.Extensions.Logging; +using System.Net.Http.Headers; +using System.Text.Json; namespace Microsoft.Agents.A365.DevTools.Cli.Services; @@ -72,8 +73,7 @@ public async Task EnsureBlueprintPermissionGrantAsync( return false; } - using var httpClient = new HttpClient(); - httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", graphToken); + using var httpClient = HttpClientFactory.CreateAuthenticatedClient(graphToken); // Step 1: Get or create service principal for custom client app _logger.LogInformation(" Looking up service principal for client app (ID: {AppId})", callingAppId); diff --git a/src/Microsoft.Agents.A365.DevTools.Cli/Services/GraphApiService.cs b/src/Microsoft.Agents.A365.DevTools.Cli/Services/GraphApiService.cs index 3d765bd9..99cf1495 100644 --- a/src/Microsoft.Agents.A365.DevTools.Cli/Services/GraphApiService.cs +++ b/src/Microsoft.Agents.A365.DevTools.Cli/Services/GraphApiService.cs @@ -1,14 +1,14 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using System.Net.Http.Headers; -using System.Text; -using System.Text.Json; -using System.Linq; using Microsoft.Agents.A365.DevTools.Cli.Constants; using Microsoft.Agents.A365.DevTools.Cli.Models; +using Microsoft.Agents.A365.DevTools.Cli.Services.Internal; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; +using System.Net.Http.Headers; +using System.Text; +using System.Text.Json; namespace Microsoft.Agents.A365.DevTools.Cli.Services; @@ -43,7 +43,7 @@ public GraphApiService(ILogger logger, CommandExecutor executor { _logger = logger; _executor = executor; - _httpClient = handler != null ? new HttpClient(handler) : new HttpClient(); + _httpClient = handler != null ? new HttpClient(handler) : HttpClientFactory.CreateAuthenticatedClient(); _tokenProvider = tokenProvider; }