From 555219a987b2aad4c63c307411e66aea3b3ed9d7 Mon Sep 17 00:00:00 2001 From: Bogdan Gavril Date: Fri, 22 May 2026 00:59:01 +0100 Subject: [PATCH 1/2] Add GovFr, GovDe, GovSg to AzureCloudInstance enum Add sovereign cloud values to AzureCloudInstance for Bleu (France), Delos (Germany), and GovSG (Singapore). Update AuthorityInfo.GetCloudUrl() to map the new values to their login endpoints and update all PublicAPI.Unshipped.txt files. Fixes #5706 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../AppConfig/AuthorityInfo.cs | 6 ++++++ .../AppConfig/AzureCloud.cs | 15 +++++++++++++++ .../PublicApi/net462/PublicAPI.Unshipped.txt | 3 +++ .../PublicApi/net472/PublicAPI.Unshipped.txt | 3 +++ .../net8.0-android/PublicAPI.Unshipped.txt | 3 +++ .../PublicApi/net8.0-ios/PublicAPI.Unshipped.txt | 3 +++ .../PublicApi/net8.0/PublicAPI.Unshipped.txt | 3 +++ .../netstandard2.0/PublicAPI.Unshipped.txt | 3 +++ 8 files changed, 39 insertions(+) diff --git a/src/client/Microsoft.Identity.Client/AppConfig/AuthorityInfo.cs b/src/client/Microsoft.Identity.Client/AppConfig/AuthorityInfo.cs index 66b6d69352..744237ef7a 100644 --- a/src/client/Microsoft.Identity.Client/AppConfig/AuthorityInfo.cs +++ b/src/client/Microsoft.Identity.Client/AppConfig/AuthorityInfo.cs @@ -261,6 +261,12 @@ internal static string GetCloudUrl(AzureCloudInstance azureCloudInstance) return "https://login.microsoftonline.de"; case AzureCloudInstance.AzureUsGovernment: return "https://login.microsoftonline.us"; + case AzureCloudInstance.GovFr: + return "https://login.sovcloud-identity.fr"; + case AzureCloudInstance.GovDe: + return "https://login.sovcloud-identity.de"; + case AzureCloudInstance.GovSg: + return "https://login.sovcloud-identity.sg"; default: throw new ArgumentException(nameof(azureCloudInstance)); } diff --git a/src/client/Microsoft.Identity.Client/AppConfig/AzureCloud.cs b/src/client/Microsoft.Identity.Client/AppConfig/AzureCloud.cs index 721742badc..7b33286138 100644 --- a/src/client/Microsoft.Identity.Client/AppConfig/AzureCloud.cs +++ b/src/client/Microsoft.Identity.Client/AppConfig/AzureCloud.cs @@ -31,5 +31,20 @@ public enum AzureCloudInstance /// US Government cloud. Maps to https://login.microsoftonline.us /// AzureUsGovernment, + + /// + /// French sovereign cloud (Bleu). Maps to https://login.sovcloud-identity.fr + /// + GovFr, + + /// + /// German sovereign cloud (Delos). Maps to https://login.sovcloud-identity.de + /// + GovDe, + + /// + /// Singapore Government cloud. Maps to https://login.sovcloud-identity.sg + /// + GovSg, }; } diff --git a/src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Unshipped.txt b/src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Unshipped.txt index 99e725f55b..36fb056ffd 100644 --- a/src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Unshipped.txt +++ b/src/client/Microsoft.Identity.Client/PublicApi/net462/PublicAPI.Unshipped.txt @@ -5,3 +5,6 @@ Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.CredentialEvalu Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.MtlsCertificate.get -> System.Security.Cryptography.X509Certificates.X509Certificate2 static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithCachePartitionKey(this Microsoft.Identity.Client.BaseAbstractAcquireTokenParameterBuilder builder, string key, string value) -> T static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithReservedScopes(this Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder builder, bool offlineAccessScope) -> Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder +Microsoft.Identity.Client.AzureCloudInstance.GovFr = 5 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovDe = 6 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovSg = 7 -> Microsoft.Identity.Client.AzureCloudInstance diff --git a/src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Unshipped.txt b/src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Unshipped.txt index 99e725f55b..36fb056ffd 100644 --- a/src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Unshipped.txt +++ b/src/client/Microsoft.Identity.Client/PublicApi/net472/PublicAPI.Unshipped.txt @@ -5,3 +5,6 @@ Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.CredentialEvalu Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.MtlsCertificate.get -> System.Security.Cryptography.X509Certificates.X509Certificate2 static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithCachePartitionKey(this Microsoft.Identity.Client.BaseAbstractAcquireTokenParameterBuilder builder, string key, string value) -> T static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithReservedScopes(this Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder builder, bool offlineAccessScope) -> Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder +Microsoft.Identity.Client.AzureCloudInstance.GovFr = 5 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovDe = 6 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovSg = 7 -> Microsoft.Identity.Client.AzureCloudInstance diff --git a/src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Unshipped.txt b/src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Unshipped.txt index 99e725f55b..36fb056ffd 100644 --- a/src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Unshipped.txt +++ b/src/client/Microsoft.Identity.Client/PublicApi/net8.0-android/PublicAPI.Unshipped.txt @@ -5,3 +5,6 @@ Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.CredentialEvalu Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.MtlsCertificate.get -> System.Security.Cryptography.X509Certificates.X509Certificate2 static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithCachePartitionKey(this Microsoft.Identity.Client.BaseAbstractAcquireTokenParameterBuilder builder, string key, string value) -> T static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithReservedScopes(this Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder builder, bool offlineAccessScope) -> Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder +Microsoft.Identity.Client.AzureCloudInstance.GovFr = 5 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovDe = 6 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovSg = 7 -> Microsoft.Identity.Client.AzureCloudInstance diff --git a/src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Unshipped.txt b/src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Unshipped.txt index 99e725f55b..36fb056ffd 100644 --- a/src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Unshipped.txt +++ b/src/client/Microsoft.Identity.Client/PublicApi/net8.0-ios/PublicAPI.Unshipped.txt @@ -5,3 +5,6 @@ Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.CredentialEvalu Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.MtlsCertificate.get -> System.Security.Cryptography.X509Certificates.X509Certificate2 static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithCachePartitionKey(this Microsoft.Identity.Client.BaseAbstractAcquireTokenParameterBuilder builder, string key, string value) -> T static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithReservedScopes(this Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder builder, bool offlineAccessScope) -> Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder +Microsoft.Identity.Client.AzureCloudInstance.GovFr = 5 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovDe = 6 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovSg = 7 -> Microsoft.Identity.Client.AzureCloudInstance diff --git a/src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Unshipped.txt b/src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Unshipped.txt index 99e725f55b..36fb056ffd 100644 --- a/src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Unshipped.txt +++ b/src/client/Microsoft.Identity.Client/PublicApi/net8.0/PublicAPI.Unshipped.txt @@ -5,3 +5,6 @@ Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.CredentialEvalu Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.MtlsCertificate.get -> System.Security.Cryptography.X509Certificates.X509Certificate2 static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithCachePartitionKey(this Microsoft.Identity.Client.BaseAbstractAcquireTokenParameterBuilder builder, string key, string value) -> T static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithReservedScopes(this Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder builder, bool offlineAccessScope) -> Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder +Microsoft.Identity.Client.AzureCloudInstance.GovFr = 5 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovDe = 6 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovSg = 7 -> Microsoft.Identity.Client.AzureCloudInstance diff --git a/src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Unshipped.txt b/src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Unshipped.txt index 99e725f55b..36fb056ffd 100644 --- a/src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Unshipped.txt +++ b/src/client/Microsoft.Identity.Client/PublicApi/netstandard2.0/PublicAPI.Unshipped.txt @@ -5,3 +5,6 @@ Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.CredentialEvalu Microsoft.Identity.Client.AuthScheme.CredentialEvaluationContext.MtlsCertificate.get -> System.Security.Cryptography.X509Certificates.X509Certificate2 static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithCachePartitionKey(this Microsoft.Identity.Client.BaseAbstractAcquireTokenParameterBuilder builder, string key, string value) -> T static Microsoft.Identity.Client.Extensibility.AcquireTokenParameterBuilderExtensions.WithReservedScopes(this Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder builder, bool offlineAccessScope) -> Microsoft.Identity.Client.AcquireTokenByAuthorizationCodeParameterBuilder +Microsoft.Identity.Client.AzureCloudInstance.GovFr = 5 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovDe = 6 -> Microsoft.Identity.Client.AzureCloudInstance +Microsoft.Identity.Client.AzureCloudInstance.GovSg = 7 -> Microsoft.Identity.Client.AzureCloudInstance From 13608147100d3fafaef0a2cc17e03364faec6c2a Mon Sep 17 00:00:00 2001 From: Bogdan Gavril Date: Fri, 22 May 2026 12:08:34 +0100 Subject: [PATCH 2/2] Add unit tests for GovFr, GovDe, GovSg sovereign cloud authority mappings Extend TestAuthorityPermutations with DataRow entries for the three new AzureCloudInstance values to verify GetCloudUrl returns the correct login.sovcloud-identity.* endpoints. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../AppConfigTests/PublicClientApplicationBuilderTests.cs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/Microsoft.Identity.Test.Unit/AppConfigTests/PublicClientApplicationBuilderTests.cs b/tests/Microsoft.Identity.Test.Unit/AppConfigTests/PublicClientApplicationBuilderTests.cs index e24cc9ce63..4aaf68063f 100644 --- a/tests/Microsoft.Identity.Test.Unit/AppConfigTests/PublicClientApplicationBuilderTests.cs +++ b/tests/Microsoft.Identity.Test.Unit/AppConfigTests/PublicClientApplicationBuilderTests.cs @@ -358,6 +358,12 @@ public void EnsureCreatePublicClientWithAzureAdMyOrgAndValidTenantSucceeds() [DataRow(AzureCloudInstance.AzureChina, AadAuthorityAudience.AzureAdMultipleOrgs, "https://login.chinacloudapi.cn/organizations/", DisplayName = "AzureChina + AzureAdMultipleOrgs")] [DataRow(AzureCloudInstance.AzureChina, AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount, "https://login.chinacloudapi.cn/common/", DisplayName = "AzureChina + AzureAdAndPersonalMicrosoftAccount")] [DataRow(AzureCloudInstance.AzureChina, AadAuthorityAudience.PersonalMicrosoftAccount, "https://login.chinacloudapi.cn/consumers/", DisplayName = "AzureChina + PersonalMicrosoftAccount")] + [DataRow(AzureCloudInstance.GovFr, AadAuthorityAudience.AzureAdMultipleOrgs, "https://login.sovcloud-identity.fr/organizations/", DisplayName = "GovFr + AzureAdMultipleOrgs")] + [DataRow(AzureCloudInstance.GovFr, AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount, "https://login.sovcloud-identity.fr/common/", DisplayName = "GovFr + AzureAdAndPersonalMicrosoftAccount")] + [DataRow(AzureCloudInstance.GovDe, AadAuthorityAudience.AzureAdMultipleOrgs, "https://login.sovcloud-identity.de/organizations/", DisplayName = "GovDe + AzureAdMultipleOrgs")] + [DataRow(AzureCloudInstance.GovDe, AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount, "https://login.sovcloud-identity.de/common/", DisplayName = "GovDe + AzureAdAndPersonalMicrosoftAccount")] + [DataRow(AzureCloudInstance.GovSg, AadAuthorityAudience.AzureAdMultipleOrgs, "https://login.sovcloud-identity.sg/organizations/", DisplayName = "GovSg + AzureAdMultipleOrgs")] + [DataRow(AzureCloudInstance.GovSg, AadAuthorityAudience.AzureAdAndPersonalMicrosoftAccount, "https://login.sovcloud-identity.sg/common/", DisplayName = "GovSg + AzureAdAndPersonalMicrosoftAccount")] public void TestAuthorityPermutations( AzureCloudInstance cloudInstance, AadAuthorityAudience audience,