From d86d2a7976f1d0ddef8de87065c77bd83190c040 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 27 Feb 2026 15:10:03 +0000
Subject: [PATCH 1/5] Initial plan
From 80d2e8633458321e93c5dc43e704e60843759982 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Fri, 27 Feb 2026 15:17:19 +0000
Subject: [PATCH 2/5] Remove hardcoded sovereign cloud presets, use
configuration-only approach
Remove static preset instances (USGov, USGovDoD, China, Public) and
FromName() from CloudEnvironment. Make constructor use default parameter
values matching existing public cloud defaults. Remove Cloud string
property from TeamsSettings. All sovereign cloud configuration now
comes from appsettings.json endpoint properties or programmatic
CloudEnvironment construction.
Addresses review feedback from rido-min: don't hardcode Entra URLs
we don't own in the codebase.
Co-authored-by: rido-min <14916339+rido-min@users.noreply.github.com>
---
.../Auth/ClientCredentials.cs | 2 +-
.../Auth/CloudEnvironment.cs | 106 +++---------------
Libraries/Microsoft.Teams.Apps/App.cs | 2 +-
.../TeamsSettings.cs | 24 ++--
.../Extensions/TeamsValidationSettings.cs | 2 +-
.../Auth/CloudEnvironmentTests.cs | 105 +++++------------
6 files changed, 56 insertions(+), 185 deletions(-)
diff --git a/Libraries/Microsoft.Teams.Api/Auth/ClientCredentials.cs b/Libraries/Microsoft.Teams.Api/Auth/ClientCredentials.cs
index e198eb73..bb04a40b 100644
--- a/Libraries/Microsoft.Teams.Api/Auth/ClientCredentials.cs
+++ b/Libraries/Microsoft.Teams.Api/Auth/ClientCredentials.cs
@@ -10,7 +10,7 @@ public class ClientCredentials : IHttpCredentials
public string ClientId { get; set; }
public string ClientSecret { get; set; }
public string? TenantId { get; set; }
- public CloudEnvironment Cloud { get; set; } = CloudEnvironment.Public;
+ public CloudEnvironment Cloud { get; set; } = new();
public ClientCredentials(string clientId, string clientSecret)
{
diff --git a/Libraries/Microsoft.Teams.Api/Auth/CloudEnvironment.cs b/Libraries/Microsoft.Teams.Api/Auth/CloudEnvironment.cs
index 7910727a..6cb83289 100644
--- a/Libraries/Microsoft.Teams.Api/Auth/CloudEnvironment.cs
+++ b/Libraries/Microsoft.Teams.Api/Auth/CloudEnvironment.cs
@@ -5,61 +5,60 @@ namespace Microsoft.Teams.Api.Auth;
///
/// Bundles all cloud-specific service endpoints for a given Azure environment.
-/// Use predefined instances (, , , )
-/// or construct a custom one.
+/// All properties default to Microsoft public (commercial) cloud values.
+/// Configure endpoints via appsettings.json or programmatically for sovereign clouds.
///
public class CloudEnvironment
{
///
- /// The Azure AD login endpoint (e.g. "https://login.microsoftonline.com").
+ /// The Azure AD login endpoint.
///
public string LoginEndpoint { get; }
///
- /// The default multi-tenant login tenant (e.g. "botframework.com").
+ /// The default login tenant.
///
public string LoginTenant { get; }
///
- /// The Bot Framework OAuth scope (e.g. "https://api.botframework.com/.default").
+ /// The Bot Framework OAuth scope.
///
public string BotScope { get; }
///
- /// The Bot Framework token service base URL (e.g. "https://token.botframework.com").
+ /// The Bot Framework token service base URL.
///
public string TokenServiceUrl { get; }
///
- /// The OpenID metadata URL for token validation (e.g. "https://login.botframework.com/v1/.well-known/openidconfiguration").
+ /// The OpenID metadata URL for token validation.
///
public string OpenIdMetadataUrl { get; }
///
- /// The token issuer for Bot Framework tokens (e.g. "https://api.botframework.com").
+ /// The token issuer for Bot Framework tokens.
///
public string TokenIssuer { get; }
///
- /// The channel service URL. Empty for public cloud; set for sovereign clouds
- /// (e.g. "https://botframework.azure.us").
+ /// The channel service URL. Empty for public cloud.
///
public string ChannelService { get; }
///
- /// The OAuth redirect URL (e.g. "https://token.botframework.com/.auth/web/redirect").
+ /// The OAuth redirect URL.
///
public string OAuthRedirectUrl { get; }
public CloudEnvironment(
- string loginEndpoint,
- string loginTenant,
- string botScope,
- string tokenServiceUrl,
- string openIdMetadataUrl,
- string tokenIssuer,
- string channelService,
- string oauthRedirectUrl)
+ string loginEndpoint = "https://login.microsoftonline.com",
+ string loginTenant = "botframework.com",
+ string botScope = "https://api.botframework.com/.default",
+ string tokenServiceUrl = "https://token.botframework.com",
+ string openIdMetadataUrl = "https://login.botframework.com/v1/.well-known/openidconfiguration",
+ string tokenIssuer = "https://api.botframework.com",
+ string channelService = "",
+ string oauthRedirectUrl = "https://token.botframework.com/.auth/web/redirect")
{
LoginEndpoint = loginEndpoint;
LoginTenant = loginTenant;
@@ -71,62 +70,6 @@ public CloudEnvironment(
OAuthRedirectUrl = oauthRedirectUrl;
}
- ///
- /// Microsoft public (commercial) cloud.
- ///
- public static readonly CloudEnvironment Public = new(
- loginEndpoint: "https://login.microsoftonline.com",
- loginTenant: "botframework.com",
- botScope: "https://api.botframework.com/.default",
- tokenServiceUrl: "https://token.botframework.com",
- openIdMetadataUrl: "https://login.botframework.com/v1/.well-known/openidconfiguration",
- tokenIssuer: "https://api.botframework.com",
- channelService: "",
- oauthRedirectUrl: "https://token.botframework.com/.auth/web/redirect"
- );
-
- ///
- /// US Government Community Cloud High (GCCH).
- ///
- public static readonly CloudEnvironment USGov = new(
- loginEndpoint: "https://login.microsoftonline.us",
- loginTenant: "MicrosoftServices.onmicrosoft.us",
- botScope: "https://api.botframework.us/.default",
- tokenServiceUrl: "https://tokengcch.botframework.azure.us",
- openIdMetadataUrl: "https://login.botframework.azure.us/v1/.well-known/openidconfiguration",
- tokenIssuer: "https://api.botframework.us",
- channelService: "https://botframework.azure.us",
- oauthRedirectUrl: "https://tokengcch.botframework.azure.us/.auth/web/redirect"
- );
-
- ///
- /// US Government Department of Defense (DoD).
- ///
- public static readonly CloudEnvironment USGovDoD = new(
- loginEndpoint: "https://login.microsoftonline.us",
- loginTenant: "MicrosoftServices.onmicrosoft.us",
- botScope: "https://api.botframework.us/.default",
- tokenServiceUrl: "https://apiDoD.botframework.azure.us",
- openIdMetadataUrl: "https://login.botframework.azure.us/v1/.well-known/openidconfiguration",
- tokenIssuer: "https://api.botframework.us",
- channelService: "https://botframework.azure.us",
- oauthRedirectUrl: "https://apiDoD.botframework.azure.us/.auth/web/redirect"
- );
-
- ///
- /// China cloud (21Vianet).
- ///
- public static readonly CloudEnvironment China = new(
- loginEndpoint: "https://login.partner.microsoftonline.cn",
- loginTenant: "microsoftservices.partner.onmschina.cn",
- botScope: "https://api.botframework.azure.cn/.default",
- tokenServiceUrl: "https://token.botframework.azure.cn",
- openIdMetadataUrl: "https://login.botframework.azure.cn/v1/.well-known/openidconfiguration",
- tokenIssuer: "https://api.botframework.azure.cn",
- channelService: "https://botframework.azure.cn",
- oauthRedirectUrl: "https://token.botframework.azure.cn/.auth/web/redirect"
- );
-
///
/// Creates a new by applying non-null overrides on top of this instance.
/// Returns the same instance if all overrides are null (no allocation).
@@ -159,17 +102,4 @@ tokenServiceUrl is null && openIdMetadataUrl is null && tokenIssuer is null &&
oauthRedirectUrl ?? OAuthRedirectUrl
);
}
-
- ///
- /// Resolves a cloud environment name (case-insensitive) to its corresponding instance.
- /// Valid names: "Public", "USGov", "USGovDoD", "China".
- ///
- public static CloudEnvironment FromName(string name) => name.ToLowerInvariant() switch
- {
- "public" => Public,
- "usgov" => USGov,
- "usgovdod" => USGovDoD,
- "china" => China,
- _ => throw new ArgumentException($"Unknown cloud environment: '{name}'. Valid values are: Public, USGov, USGovDoD, China.", nameof(name))
- };
}
diff --git a/Libraries/Microsoft.Teams.Apps/App.cs b/Libraries/Microsoft.Teams.Apps/App.cs
index ed2dd1f6..d61efb85 100644
--- a/Libraries/Microsoft.Teams.Apps/App.cs
+++ b/Libraries/Microsoft.Teams.Apps/App.cs
@@ -51,7 +51,7 @@ internal string UserAgent
public App(AppOptions? options = null)
{
- var cloud = options?.Cloud ?? CloudEnvironment.Public;
+ var cloud = options?.Cloud ?? new CloudEnvironment();
Logger = options?.Logger ?? new ConsoleLogger();
Storage = options?.Storage ?? new LocalStorage