From 0b1cfc47ed9fcb377b651df7932960a80042bb92 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Mon, 3 Nov 2025 13:51:23 -0800 Subject: [PATCH 1/3] honor AZURE_CLIENT_ID in mi --- .../Authentication/CustomChainedCredential.cs | 30 +- .../CustomChainedCredentialTests.cs | 382 ++++++++++++++++++ docs/Authentication.md | 13 +- servers/Azure.Mcp.Server/CHANGELOG.md | 2 + servers/Azure.Mcp.Server/TROUBLESHOOTING.md | 30 +- 5 files changed, 447 insertions(+), 10 deletions(-) create mode 100644 core/Azure.Mcp.Core/tests/Azure.Mcp.Core.UnitTests/Services/Azure/Authentication/CustomChainedCredentialTests.cs diff --git a/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs b/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs index 7bad1661e7..610441545e 100644 --- a/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs +++ b/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs @@ -26,6 +26,10 @@ namespace Azure.Mcp.Core.Services.Azure.Authentication; /// Special behavior: When running in VS Code context (VSCODE_PID environment variable is set) and AZURE_TOKEN_CREDENTIALS is not explicitly specified, /// Visual Studio Code credential is automatically prioritized first in the chain. /// +/// Managed Identity Support: +/// - AZURE_CLIENT_ID: Configures User-Assigned Managed Identity with the specified client ID +/// - If AZURE_CLIENT_ID is not set or empty, System-Assigned Managed Identity is used (default) +/// /// After the credential chain, Interactive Browser Authentication with Identity Broker is always added as the final fallback. /// public class CustomChainedCredential(string? tenantId = null, ILogger? logger = null) : TokenCredential @@ -92,7 +96,14 @@ private static TokenCredential CreateCredential(string? tenantId, ILogger credenti private static void AddManagedIdentityCredential(List credentials) { - credentials.Add(new SafeTokenCredential(new ManagedIdentityCredential(), "ManagedIdentityCredential")); + // Check for AZURE_CLIENT_ID to support User-Assigned Managed Identity + string? clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"); + + ManagedIdentityCredential managedIdentityCredential; + if (!string.IsNullOrWhiteSpace(clientId)) + { + // User-Assigned Managed Identity with explicit client ID + managedIdentityCredential = new ManagedIdentityCredential(clientId); + } + else + { + // System-Assigned Managed Identity (default) + managedIdentityCredential = new ManagedIdentityCredential(); + } + + credentials.Add(new SafeTokenCredential(managedIdentityCredential, "ManagedIdentityCredential")); } private static void AddVisualStudioCredential(List credentials, string? tenantId) diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.UnitTests/Services/Azure/Authentication/CustomChainedCredentialTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.UnitTests/Services/Azure/Authentication/CustomChainedCredentialTests.cs new file mode 100644 index 0000000000..e77195f170 --- /dev/null +++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.UnitTests/Services/Azure/Authentication/CustomChainedCredentialTests.cs @@ -0,0 +1,382 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Reflection; +using Azure.Core; +using Microsoft.Extensions.Logging; +using Xunit; + +namespace Azure.Mcp.Core.UnitTests.Services.Azure.Authentication; + +/// +/// Tests for CustomChainedCredential configuration behavior. +/// These tests verify that credentials are created correctly based on environment variable settings. +/// Note: These tests verify creation behavior only. Actual authentication behavior requires live credentials. +/// +public class CustomChainedCredentialTests : IDisposable +{ + private readonly Dictionary _originalEnvVars = new(); + + public CustomChainedCredentialTests() + { + // Save original environment variables + SaveEnvironmentVariable("AZURE_TOKEN_CREDENTIALS"); + SaveEnvironmentVariable("VSCODE_PID"); + SaveEnvironmentVariable("AZURE_CLIENT_ID"); + SaveEnvironmentVariable("AZURE_MCP_ONLY_USE_BROKER_CREDENTIAL"); + } + + public void Dispose() + { + // Restore original environment variables + foreach (var (key, value) in _originalEnvVars) + { + Environment.SetEnvironmentVariable(key, value); + } + } + + private void SaveEnvironmentVariable(string name) + { + _originalEnvVars[name] = Environment.GetEnvironmentVariable(name); + } + + /// + /// Tests that default behavior (no AZURE_TOKEN_CREDENTIALS set) creates a credential successfully. + /// Expected: Uses default credential chain with InteractiveBrowserCredential fallback. + /// + [Fact] + public void DefaultBehavior_CreatesCredentialSuccessfully() + { + // Arrange: No AZURE_TOKEN_CREDENTIALS set + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", null); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests that dev mode (AZURE_TOKEN_CREDENTIALS="dev") creates a credential successfully. + /// Expected: Uses development credentials with InteractiveBrowserCredential fallback. + /// + [Fact] + public void DevMode_CreatesCredentialSuccessfully() + { + // Arrange + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", "dev"); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests that prod mode (AZURE_TOKEN_CREDENTIALS="prod") creates a credential successfully. + /// Expected: Uses production credentials (EnvironmentCredential, WorkloadIdentityCredential, ManagedIdentityCredential) + /// WITHOUT InteractiveBrowserCredential fallback. + /// + [Fact] + public void ProdMode_CreatesCredentialSuccessfully() + { + // Arrange + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", "prod"); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests that specific credential (AZURE_TOKEN_CREDENTIALS="ManagedIdentityCredential") creates successfully. + /// Expected: Uses ONLY ManagedIdentityCredential without InteractiveBrowserCredential fallback. + /// + [Fact] + public void SpecificCredential_ManagedIdentity_CreatesCredentialSuccessfully() + { + // Arrange + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", "ManagedIdentityCredential"); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests that specific credential (AZURE_TOKEN_CREDENTIALS="AzureCliCredential") creates successfully. + /// Expected: Uses ONLY AzureCliCredential without InteractiveBrowserCredential fallback. + /// + [Fact] + public void SpecificCredential_AzureCli_CreatesCredentialSuccessfully() + { + // Arrange + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", "AzureCliCredential"); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests that explicit InteractiveBrowserCredential request creates successfully. + /// Expected: Uses InteractiveBrowserCredential when explicitly requested. + /// + [Fact] + public void SpecificCredential_InteractiveBrowser_CreatesCredentialSuccessfully() + { + // Arrange + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", "InteractiveBrowserCredential"); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests all supported specific credential types create successfully. + /// Expected: Each credential type creates without errors. + /// + [Theory] + [InlineData("EnvironmentCredential")] + [InlineData("WorkloadIdentityCredential")] + [InlineData("VisualStudioCredential")] + [InlineData("VisualStudioCodeCredential")] + [InlineData("AzurePowerShellCredential")] + [InlineData("AzureDeveloperCliCredential")] + public void SpecificCredential_VariousTypes_CreateCredentialSuccessfully(string credentialType) + { + // Arrange + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", credentialType); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests that User-Assigned Managed Identity (AZURE_CLIENT_ID set) creates successfully. + /// Expected: ManagedIdentityCredential is configured with the specified clientId. + /// + [Fact] + public void ManagedIdentityCredential_WithClientId_CreatesCredentialSuccessfully() + { + // Arrange + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", "ManagedIdentityCredential"); + Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", "12345678-1234-1234-1234-123456789012"); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests that System-Assigned Managed Identity (no AZURE_CLIENT_ID) creates successfully. + /// Expected: ManagedIdentityCredential is configured for system-assigned identity. + /// + [Fact] + public void ManagedIdentityCredential_WithoutClientId_CreatesCredentialSuccessfully() + { + // Arrange + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", "ManagedIdentityCredential"); + Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", null); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests that AZURE_CLIENT_ID environment variable value is correctly read and used. + /// This validates that the exact client ID value is passed to ManagedIdentityCredential. + /// This verifies the fix for GitHub issue #1030 - AZURE_CLIENT_ID support. + /// + [Theory] + [InlineData("12345678-1234-1234-1234-123456789012")] + [InlineData("abcdef00-1111-2222-3333-444444444444")] + [InlineData("test-client-id")] + public void ManagedIdentityCredential_WithClientId_UsesCorrectClientIdValue(string expectedClientId) + { + // Arrange + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", "ManagedIdentityCredential"); + Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", expectedClientId); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert - Verify the credential was created successfully + Assert.NotNull(credential); + + // Verify AZURE_CLIENT_ID environment variable is set correctly + var actualClientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"); + Assert.Equal(expectedClientId, actualClientId); + } + + /// + /// Tests that empty AZURE_CLIENT_ID is treated as System-Assigned Managed Identity. + /// + [Theory] + [InlineData(null)] + [InlineData("")] + [InlineData(" ")] + public void ManagedIdentityCredential_WithEmptyClientId_UsesSystemAssignedIdentity(string? clientId) + { + // Arrange + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", "ManagedIdentityCredential"); + Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", clientId); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert - Should create successfully even with empty/null client ID + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests that AZURE_CLIENT_ID is only used with ManagedIdentityCredential in prod mode. + /// When using prod mode, AZURE_CLIENT_ID should be respected for Managed Identity. + /// + [Fact] + public void ProdMode_WithClientId_UsesUserAssignedManagedIdentity() + { + // Arrange + string expectedClientId = "87654321-4321-4321-4321-210987654321"; + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", "prod"); + Environment.SetEnvironmentVariable("AZURE_CLIENT_ID", expectedClientId); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + + // Verify AZURE_CLIENT_ID is still set + var actualClientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"); + Assert.Equal(expectedClientId, actualClientId); + } + + /// + /// Tests that "only broker credential" mode creates InteractiveBrowserCredential successfully. + /// Expected: Uses only InteractiveBrowserCredential with broker support. + /// + [Fact] + public void OnlyUseBrokerCredential_CreatesCredentialSuccessfully() + { + // Arrange + Environment.SetEnvironmentVariable("AZURE_MCP_ONLY_USE_BROKER_CREDENTIAL", "true"); + Environment.SetEnvironmentVariable("VSCODE_PID", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests that VS Code context without explicit setting creates credential successfully. + /// Expected: When VSCODE_PID is set and AZURE_TOKEN_CREDENTIALS is not set, + /// prioritizes VS Code credential in the chain. + /// + [Fact] + public void VSCodeContext_WithoutExplicitSetting_CreatesCredentialSuccessfully() + { + // Arrange + Environment.SetEnvironmentVariable("VSCODE_PID", "12345"); + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", null); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Tests that VS Code context with explicit prod setting respects the explicit setting. + /// Expected: When both VSCODE_PID and AZURE_TOKEN_CREDENTIALS are set, + /// AZURE_TOKEN_CREDENTIALS takes precedence. + /// + [Fact] + public void VSCodeContext_WithExplicitProdSetting_CreatesCredentialSuccessfully() + { + // Arrange + Environment.SetEnvironmentVariable("VSCODE_PID", "12345"); + Environment.SetEnvironmentVariable("AZURE_TOKEN_CREDENTIALS", "prod"); + + // Act + var credential = CreateCustomChainedCredential(); + + // Assert + Assert.NotNull(credential); + Assert.IsAssignableFrom(credential); + } + + /// + /// Helper method to create CustomChainedCredential using reflection since it's an internal class. + /// + private static TokenCredential CreateCustomChainedCredential() + { + var assembly = typeof(global::Azure.Mcp.Core.Commands.CommandFactory).Assembly; + var customChainedCredentialType = assembly.GetType("Azure.Mcp.Core.Services.Azure.Authentication.CustomChainedCredential"); + + Assert.NotNull(customChainedCredentialType); + + var constructor = customChainedCredentialType.GetConstructors(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) + .FirstOrDefault(c => + { + var parameters = c.GetParameters(); + return parameters.Length == 2 && + parameters[0].ParameterType == typeof(string) && + parameters[1].ParameterType == typeof(ILogger<>).MakeGenericType(customChainedCredentialType); + }); + + Assert.NotNull(constructor); + + var credential = constructor.Invoke([null, null]) as TokenCredential; + Assert.NotNull(credential); + + return credential; + } +} diff --git a/docs/Authentication.md b/docs/Authentication.md index af8201c49f..2ab55c8d35 100644 --- a/docs/Authentication.md +++ b/docs/Authentication.md @@ -61,7 +61,18 @@ For Kubernetes workloads or Azure-hosted apps, set the following environment var export AZURE_TOKEN_CREDENTIALS=prod ``` -This configuration modifies the credential chain to use only production credentials (Environment, Workload Identity, and Managed Identity), in that order. +This configuration modifies the credential chain to use only production credentials (Environment, Workload Identity, and Managed Identity), in that order. No interactive browser fallback is added. + +#### User-Assigned Managed Identity + +To use a User-Assigned Managed Identity in production environments (Azure Web Apps, Function Apps, Container Apps, AKS, etc.), set both environment variables: + +```bash +export AZURE_TOKEN_CREDENTIALS=prod +export AZURE_CLIENT_ID="" +``` + +If `AZURE_CLIENT_ID` is not set, the system will use System-Assigned Managed Identity by default. ### Development Environments diff --git a/servers/Azure.Mcp.Server/CHANGELOG.md b/servers/Azure.Mcp.Server/CHANGELOG.md index 1c604a022b..d1d82d1ed7 100644 --- a/servers/Azure.Mcp.Server/CHANGELOG.md +++ b/servers/Azure.Mcp.Server/CHANGELOG.md @@ -6,6 +6,8 @@ The Azure MCP Server updates automatically by default whenever a new release com ### Features Added +- Add support for User-Assigned Managed Identity via `AZURE_CLIENT_ID` environment variable [[#1030](https://github.com/microsoft/mcp/issues/1030)] + ### Breaking Changes ### Bugs Fixed diff --git a/servers/Azure.Mcp.Server/TROUBLESHOOTING.md b/servers/Azure.Mcp.Server/TROUBLESHOOTING.md index 040c40cb6c..204981f3ec 100644 --- a/servers/Azure.Mcp.Server/TROUBLESHOOTING.md +++ b/servers/Azure.Mcp.Server/TROUBLESHOOTING.md @@ -382,24 +382,33 @@ To use only **production credentials** (Environment, Workload Identity, Managed AZURE_TOKEN_CREDENTIALS=prod ``` -To use only **development credentials** (Visual Studio, Visual Studio Code, Azure CLI, Azure PowerShell, Azure Developer CLI), set: +When `prod` is used: +- The credential chain becomes: `Environment → Workload Identity → Managed Identity` +- **No interactive browser fallback** is added (fail fast if credentials unavailable) +- For **User-Assigned Managed Identity**, also set `AZURE_CLIENT_ID` to the client ID of the managed identity + ```bash -AZURE_TOKEN_CREDENTIALS=dev -``` +# System-Assigned Managed Identity (default) +AZURE_TOKEN_CREDENTIALS=prod -When `prod` is used, the credential chain becomes: +# User-Assigned Managed Identity +AZURE_TOKEN_CREDENTIALS=prod +AZURE_CLIENT_ID="" ``` -Environment → Workload Identity → Managed Identity + +To use only **development credentials** (Visual Studio, Visual Studio Code, Azure CLI, Azure PowerShell, Azure Developer CLI), set: +```bash +AZURE_TOKEN_CREDENTIALS=dev ``` When `dev` is used, the credential chain becomes: ``` -Visual Studio → Visual Studio Code → Azure CLI → Azure PowerShell → Azure Developer CLI +Visual Studio → Visual Studio Code → Azure CLI → Azure PowerShell → Azure Developer CLI → InteractiveBrowserCredential fallback ``` #### Use Specific Credentials Only -To use only a specific credential type, set `AZURE_TOKEN_CREDENTIALS` to the name of a single credential: +To use only a specific credential type, set `AZURE_TOKEN_CREDENTIALS` to the name of a single credential. **Note: No interactive browser fallback will be added.** ```bash # Use only Azure CLI credential @@ -411,6 +420,13 @@ AZURE_TOKEN_CREDENTIALS=VisualStudioCodeCredential # Use only Environment credential (for CI/CD scenarios) AZURE_TOKEN_CREDENTIALS=EnvironmentCredential +# Use only Managed Identity credential +AZURE_TOKEN_CREDENTIALS=ManagedIdentityCredential + +# For User-Assigned Managed Identity, also set AZURE_CLIENT_ID +AZURE_TOKEN_CREDENTIALS=ManagedIdentityCredential +AZURE_CLIENT_ID="" + # Use only Interactive Browser credential AZURE_TOKEN_CREDENTIALS=InteractiveBrowserCredential ``` From f56f85e6b74a54e13081bfbed985688b9c5015a3 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Mon, 3 Nov 2025 14:12:07 -0800 Subject: [PATCH 2/3] update --- .../Azure/Authentication/CustomChainedCredential.cs | 6 +++--- .../Azure/Authentication/CustomChainedCredentialTests.cs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs b/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs index 610441545e..e77b798ff4 100644 --- a/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs +++ b/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs @@ -103,7 +103,7 @@ private static TokenCredential CreateCredential(string? tenantId, ILogger credentia { // Check for AZURE_CLIENT_ID to support User-Assigned Managed Identity string? clientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"); - + ManagedIdentityCredential managedIdentityCredential; if (!string.IsNullOrWhiteSpace(clientId)) { @@ -258,7 +258,7 @@ private static void AddManagedIdentityCredential(List credentia // System-Assigned Managed Identity (default) managedIdentityCredential = new ManagedIdentityCredential(); } - + credentials.Add(new SafeTokenCredential(managedIdentityCredential, "ManagedIdentityCredential")); } diff --git a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.UnitTests/Services/Azure/Authentication/CustomChainedCredentialTests.cs b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.UnitTests/Services/Azure/Authentication/CustomChainedCredentialTests.cs index e77195f170..3eeb221f0b 100644 --- a/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.UnitTests/Services/Azure/Authentication/CustomChainedCredentialTests.cs +++ b/core/Azure.Mcp.Core/tests/Azure.Mcp.Core.UnitTests/Services/Azure/Authentication/CustomChainedCredentialTests.cs @@ -241,7 +241,7 @@ public void ManagedIdentityCredential_WithClientId_UsesCorrectClientIdValue(stri // Assert - Verify the credential was created successfully Assert.NotNull(credential); - + // Verify AZURE_CLIENT_ID environment variable is set correctly var actualClientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"); Assert.Equal(expectedClientId, actualClientId); @@ -288,7 +288,7 @@ public void ProdMode_WithClientId_UsesUserAssignedManagedIdentity() // Assert Assert.NotNull(credential); Assert.IsAssignableFrom(credential); - + // Verify AZURE_CLIENT_ID is still set var actualClientId = Environment.GetEnvironmentVariable("AZURE_CLIENT_ID"); Assert.Equal(expectedClientId, actualClientId); From a021d5d6cf645704094accd62af241bcad3dc5c9 Mon Sep 17 00:00:00 2001 From: Xiang Yan Date: Tue, 4 Nov 2025 13:46:26 -0800 Subject: [PATCH 3/3] update --- .../Authentication/CustomChainedCredential.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs b/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs index e77b798ff4..9e58f96144 100644 --- a/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs +++ b/core/Azure.Mcp.Core/src/Services/Azure/Authentication/CustomChainedCredential.cs @@ -96,10 +96,16 @@ private static TokenCredential CreateCredential(string? tenantId, ILogger