diff --git a/.gitignore b/.gitignore
index 1d4d1e43..c1b514c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -453,4 +453,6 @@ FodyWeavers.xsd
*.sln.iml
### VisualStudio Patch ###
-# Additional files built by Visual Studio
\ No newline at end of file
+# Additional files built by Visual Studio
+
+.env.local
diff --git a/.vscode/launch.json b/.vscode/launch.json
index a07f03d1..69664299 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -10,7 +10,7 @@
"request": "launch",
"preLaunchTask": "build sample",
// If you have changed target frameworks, make sure to update the program path.
- "program": "${workspaceFolder}/src/sample/bin/Debug/net7.0/sample.dll",
+ "program": "${workspaceFolder}/src/sample/bin/Debug/net8.0/sample.dll",
"args": [
"login",
"--strategy",
@@ -30,7 +30,7 @@
"request": "launch",
"preLaunchTask": "build sample",
// If you have changed target frameworks, make sure to update the program path.
- "program": "${workspaceFolder}/src/sample/bin/Debug/net7.0/sample.dll",
+ "program": "${workspaceFolder}/src/sample/bin/Debug/net8.0/sample.dll",
"args": [
"login",
"--strategy",
@@ -46,7 +46,7 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build sample",
- "program": "${workspaceFolder}/src/sample/bin/Debug/net7.0/sample.dll",
+ "program": "${workspaceFolder}/src/sample/bin/Debug/net8.0/sample.dll",
"args": [
"login",
"--strategy",
@@ -67,7 +67,7 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build sample",
- "program": "${workspaceFolder}/src/sample/bin/Debug/net7.0/sample.dll",
+ "program": "${workspaceFolder}/src/sample/bin/Debug/net8.0/sample.dll",
"args": [
"login",
"--strategy",
@@ -77,6 +77,23 @@
"--client-id",
"e49807f2-94cc-4f59-9e14-be2a37eab7c2"
],
+ "envFile": "${workspaceFolder}/.env.local",
+ "cwd": "${workspaceFolder}/src/sample",
+ "console": "internalConsole",
+ "stopAtEntry": false
+ },
+ {
+ "name": "login national cloud (sample)",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build sample",
+ "program": "${workspaceFolder}/src/sample/bin/Debug/net8.0/sample.dll",
+ "args": [
+ "login",
+ "--environment",
+ "US_GOV"
+ ],
+ "envFile": "${workspaceFolder}/.env.local",
"cwd": "${workspaceFolder}/src/sample",
"console": "internalConsole",
"stopAtEntry": false
@@ -86,13 +103,32 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build sample",
- "program": "${workspaceFolder}/src/sample/bin/Debug/net7.0/sample.dll",
+ "program": "${workspaceFolder}/src/sample/bin/Debug/net8.0/sample.dll",
"args": [
"users",
"list",
"--debug",
"--top",
- "2"
+ "2",
+ "--headers",
+ "sample=header"
+ ],
+ "envFile": "${workspaceFolder}/.env.local",
+ "cwd": "${workspaceFolder}/src/sample",
+ "console": "integratedTerminal",
+ "stopAtEntry": false,
+ "justMyCode": false
+ },
+ {
+ "name": "me get (sample)",
+ "type": "coreclr",
+ "request": "launch",
+ "preLaunchTask": "build sample",
+ "program": "${workspaceFolder}/src/sample/bin/Debug/net8.0/sample.dll",
+ "args": [
+ "me",
+ "get",
+ "--debug"
],
"cwd": "${workspaceFolder}/src/sample",
"console": "integratedTerminal",
@@ -103,7 +139,7 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build sample",
- "program": "${workspaceFolder}/src/sample/bin/Debug/net7.0/sample.dll",
+ "program": "${workspaceFolder}/src/sample/bin/Debug/net8.0/sample.dll",
"args": [
"logout",
"--debug"
@@ -117,9 +153,8 @@
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build sample",
- "program": "${workspaceFolder}/src/sample/bin/Debug/net7.0/sample.dll",
+ "program": "${workspaceFolder}/src/sample/bin/Debug/net8.0/sample.dll",
"args": [
- "login",
"--help"
],
"cwd": "${workspaceFolder}/src/sample",
@@ -132,4 +167,4 @@
"request": "attach"
}
]
-}
\ No newline at end of file
+}
diff --git a/src/Microsoft.Graph.Cli.Core/Authentication/AuthenticationServiceFactory.cs b/src/Microsoft.Graph.Cli.Core/Authentication/AuthenticationServiceFactory.cs
index e6f14091..594f48ee 100644
--- a/src/Microsoft.Graph.Cli.Core/Authentication/AuthenticationServiceFactory.cs
+++ b/src/Microsoft.Graph.Cli.Core/Authentication/AuthenticationServiceFactory.cs
@@ -41,12 +41,13 @@ public AuthenticationServiceFactory(IPathUtility pathUtility, IAuthenticationCac
/// Client Id
/// Certificate name
/// Certificate thumb-print
+ /// The national cloud environment. Either 'Global', 'US_GOV', 'US_GOV_DOD' or 'China'
/// Cancellation token
/// Returns a login service instance.
/// When an unsupported authentication strategy is provided.
- public virtual async Task GetAuthenticationServiceAsync(AuthenticationStrategy strategy, string? tenantId, string? clientId, string? certificateName, string? certificateThumbPrint, CancellationToken cancellationToken = default)
+ public virtual async Task GetAuthenticationServiceAsync(AuthenticationStrategy strategy, string? tenantId, string? clientId, string? certificateName, string? certificateThumbPrint, CloudEnvironment environment, CancellationToken cancellationToken = default)
{
- var credential = await GetTokenCredentialAsync(strategy, tenantId, clientId, certificateName, certificateThumbPrint, cancellationToken);
+ var credential = await GetTokenCredentialAsync(strategy, tenantId, clientId, certificateName, certificateThumbPrint, environment, cancellationToken);
if (strategy == AuthenticationStrategy.DeviceCode && credential is DeviceCodeCredential deviceCred)
{
return new InteractiveLoginService(deviceCred, pathUtility);
@@ -81,35 +82,33 @@ public virtual async Task GetAuthenticationServiceAsync(Authen
/// Client Id
/// Certificate name
/// Certificate thumb-print
+ /// The cloud environment.
/// Cancellation token.
/// A token credential instance.
/// When an unsupported authentication strategy is provided.
- public virtual async Task GetTokenCredentialAsync(AuthenticationStrategy strategy, string? tenantId, string? clientId, string? certificateName, string? certificateThumbPrint, CancellationToken cancellationToken = default)
+ /// When a null url is provided for the authority host.
+ public virtual async Task GetTokenCredentialAsync(AuthenticationStrategy strategy, string? tenantId, string? clientId, string? certificateName, string? certificateThumbPrint, CloudEnvironment environment = CloudEnvironment.Global, CancellationToken cancellationToken = default)
{
- switch (strategy)
+ var authorityHost = environment.Authority();
+ return strategy switch
{
- case AuthenticationStrategy.DeviceCode:
- return await GetDeviceCodeCredentialAsync(tenantId, clientId, cancellationToken);
- case AuthenticationStrategy.InteractiveBrowser:
- return await GetInteractiveBrowserCredentialAsync(tenantId, clientId, cancellationToken);
- case AuthenticationStrategy.ClientCertificate:
- return GetClientCertificateCredential(tenantId, clientId, certificateName, certificateThumbPrint);
- case AuthenticationStrategy.Environment:
- return new EnvironmentCredential(tenantId, clientId);
- case AuthenticationStrategy.ManagedIdentity:
- return new ManagedIdentityCredential(clientId);
- default:
- throw new InvalidOperationException($"The authentication strategy {strategy} is not supported");
- }
+ AuthenticationStrategy.DeviceCode => await GetDeviceCodeCredentialAsync(tenantId, clientId, authorityHost, cancellationToken),
+ AuthenticationStrategy.InteractiveBrowser => await GetInteractiveBrowserCredentialAsync(tenantId, clientId, authorityHost, cancellationToken),
+ AuthenticationStrategy.ClientCertificate => GetClientCertificateCredential(tenantId, clientId, certificateName, certificateThumbPrint, authorityHost),
+ AuthenticationStrategy.Environment => new EnvironmentCredential(tenantId, clientId, new TokenCredentialOptions { AuthorityHost = authorityHost }),
+ AuthenticationStrategy.ManagedIdentity => new ManagedIdentityCredential(clientId, new TokenCredentialOptions { AuthorityHost = authorityHost }),
+ _ => throw new InvalidOperationException($"The authentication strategy {strategy} is not supported"),
+ };
}
- private async Task GetDeviceCodeCredentialAsync(string? tenantId, string? clientId, CancellationToken cancellationToken = default)
+ private async Task GetDeviceCodeCredentialAsync(string? tenantId, string? clientId, Uri authorityHost, CancellationToken cancellationToken = default)
{
DeviceCodeCredentialOptions credOptions = new()
{
ClientId = clientId ?? Constants.DefaultAppId,
TenantId = tenantId ?? Constants.DefaultTenant,
DisableAutomaticAuthentication = true,
+ AuthorityHost = authorityHost
};
TokenCachePersistenceOptions tokenCacheOptions = new() { Name = Constants.TokenCacheName };
@@ -119,13 +118,14 @@ private async Task GetDeviceCodeCredentialAsync(string? te
return new DeviceCodeCredential(credOptions);
}
- private async Task GetInteractiveBrowserCredentialAsync(string? tenantId, string? clientId, CancellationToken cancellationToken = default)
+ private async Task GetInteractiveBrowserCredentialAsync(string? tenantId, string? clientId, Uri authorityHost, CancellationToken cancellationToken = default)
{
InteractiveBrowserCredentialOptions credOptions = new()
{
ClientId = clientId ?? Constants.DefaultAppId,
TenantId = tenantId ?? Constants.DefaultTenant,
DisableAutomaticAuthentication = true,
+ AuthorityHost = authorityHost
};
TokenCachePersistenceOptions tokenCacheOptions = new() { Name = Constants.TokenCacheName };
@@ -135,8 +135,8 @@ private async Task GetInteractiveBrowserCredential
return new InteractiveBrowserCredential(credOptions);
}
- private ClientCertificateCredential GetClientCertificateCredential(string? tenantId, string? clientId, string? certificateName, string? certificateThumbPrint)
+ private ClientCertificateCredential GetClientCertificateCredential(string? tenantId, string? clientId, string? certificateName, string? certificateThumbPrint, Uri authorityHost)
{
- return ClientCertificateCredentialFactory.GetClientCertificateCredential(tenantId ?? Constants.DefaultTenant, clientId ?? Constants.DefaultAppId, certificateName, certificateThumbPrint);
+ return ClientCertificateCredentialFactory.GetClientCertificateCredential(tenantId ?? Constants.DefaultTenant, clientId ?? Constants.DefaultAppId, certificateName, certificateThumbPrint, authorityHost);
}
}
diff --git a/src/Microsoft.Graph.Cli.Core/Authentication/ClientCertificateCredentialFactory.cs b/src/Microsoft.Graph.Cli.Core/Authentication/ClientCertificateCredentialFactory.cs
index 590ce27f..c2741904 100644
--- a/src/Microsoft.Graph.Cli.Core/Authentication/ClientCertificateCredentialFactory.cs
+++ b/src/Microsoft.Graph.Cli.Core/Authentication/ClientCertificateCredentialFactory.cs
@@ -4,6 +4,7 @@
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Azure.Identity;
+using Microsoft.Graph.Cli.Core.Utils;
namespace Microsoft.Graph.Cli.Core.Authentication;
@@ -19,15 +20,17 @@ public static class ClientCertificateCredentialFactory
/// ClientId
/// Subject name of the certificate.
/// Thumb print of the certificate.
+ /// The entra authentication endpoint (to use with national clouds)
/// A ClientCertificateCredential
- public static ClientCertificateCredential GetClientCertificateCredential(string? tenantId, string? clientId, string? certificateName, string? certificateThumbPrint)
+ /// When a null url is provided for the authority host.
+ public static ClientCertificateCredential GetClientCertificateCredential(string? tenantId, string? clientId, string? certificateName, string? certificateThumbPrint, Uri authorityHost)
{
if (string.IsNullOrWhiteSpace(certificateName) && string.IsNullOrWhiteSpace(certificateThumbPrint))
{
throw new ArgumentException("Either a certificate name or a certificate thumb print must be provided.");
}
- ClientCertificateCredentialOptions credOptions = new();
+ ClientCertificateCredentialOptions credOptions = new() { AuthorityHost = authorityHost };
// // TODO: Enable token caching
// // Fix error:
diff --git a/src/Microsoft.Graph.Cli.Core/Authentication/CloudEnvironment.cs b/src/Microsoft.Graph.Cli.Core/Authentication/CloudEnvironment.cs
new file mode 100644
index 00000000..be4eff2d
--- /dev/null
+++ b/src/Microsoft.Graph.Cli.Core/Authentication/CloudEnvironment.cs
@@ -0,0 +1,73 @@
+using System;
+using Azure.Identity;
+using Microsoft.Graph;
+using Microsoft.Graph.Cli.Core.Utils;
+
+
+///
+/// The cloud environment to use
+///
+public enum CloudEnvironment
+{
+ ///
+ /// Global environment.
+ ///
+ Global,
+ ///
+ /// US Government cloud environment.
+ ///
+ USGov,
+ ///
+ /// US Government Department of Defense (DoD) cloud environment.
+ ///
+ USGovDoD,
+ ///
+ /// China cloud environment.
+ ///
+ China,
+}
+
+///
+/// Provides methods for the class.
+///
+public static class CloudEnvironmentExtensions
+{
+ ///
+ /// Gets the authority URL for the specified cloud environment.
+ ///
+ /// The cloud environment.
+ /// The authority URL.
+ ///
+ /// If the cloud environment is not one of the members.
+ ///
+ public static Uri Authority(this CloudEnvironment environment)
+ {
+ return environment switch
+ {
+ CloudEnvironment.Global => AzureAuthorityHosts.AzurePublicCloud,
+ CloudEnvironment.USGov or CloudEnvironment.USGovDoD => AzureAuthorityHosts.AzureGovernment,
+ CloudEnvironment.China => AzureAuthorityHosts.AzureChina,
+ _ => throw new ArgumentException("Unknown cloud environment", nameof(environment))
+ };
+ }
+
+ ///
+ /// Gets the GraphClient Cloud identifier.
+ ///
+ /// The cloud environment.
+ /// The cloud identifier to be used by the graph client.
+ ///
+ /// If the cloud environment is not one of the members.
+ ///
+ public static string GraphClientCloud(this CloudEnvironment environment)
+ {
+ return environment switch
+ {
+ CloudEnvironment.Global => GraphClientFactory.Global_Cloud,
+ CloudEnvironment.USGov => GraphClientFactory.USGOV_Cloud,
+ CloudEnvironment.USGovDoD => GraphClientFactory.USGOV_DOD_Cloud,
+ CloudEnvironment.China => GraphClientFactory.China_Cloud,
+ _ => throw new ArgumentException("Unknown cloud environment", nameof(environment))
+ };
+ }
+}
diff --git a/src/Microsoft.Graph.Cli.Core/Authentication/EnvironmentCredential.cs b/src/Microsoft.Graph.Cli.Core/Authentication/EnvironmentCredential.cs
index 70db173d..e03260d0 100644
--- a/src/Microsoft.Graph.Cli.Core/Authentication/EnvironmentCredential.cs
+++ b/src/Microsoft.Graph.Cli.Core/Authentication/EnvironmentCredential.cs
@@ -72,11 +72,11 @@ public EnvironmentCredential(string? tenantId, string? clientId, TokenCredential
bool sendCertificateChain = !string.IsNullOrEmpty(clientSendCertificateChain) &&
(clientSendCertificateChain == "1" || clientSendCertificateChain == "true");
- ClientCertificateCredentialOptions clientCertificateCredentialOptions = new ClientCertificateCredentialOptions
+ ClientCertificateCredentialOptions clientCertificateCredentialOptions = new()
{
AuthorityHost = _options.AuthorityHost,
Transport = _options.Transport,
- SendCertificateChain = sendCertificateChain
+ SendCertificateChain = sendCertificateChain,
};
// Use reflection to set internal properties.
X509Certificate2? cert;
diff --git a/src/Microsoft.Graph.Cli.Core/Commands/Authentication/LoginCommand.cs b/src/Microsoft.Graph.Cli.Core/Commands/Authentication/LoginCommand.cs
index b6045e66..65f542d0 100644
--- a/src/Microsoft.Graph.Cli.Core/Commands/Authentication/LoginCommand.cs
+++ b/src/Microsoft.Graph.Cli.Core/Commands/Authentication/LoginCommand.cs
@@ -27,6 +27,8 @@ public sealed class LoginCommand : Command
private Option certificateThumbPrintOption = new("--certificate-thumb-print", "The thumbprint of your certificate. The certificate will be retrieved from the current user's certificate store.");
+ private Option environmentOption = new("--environment", () => CloudEnvironment.Global, "Select the cloud environment to log in to. If login is run without providing an environment, Global is used.");
+
private Option strategyOption = new("--strategy", () => Constants.defaultAuthStrategy);
internal LoginCommand() : base("login", "Login and store the session for use in subsequent commands")
@@ -36,6 +38,7 @@ public sealed class LoginCommand : Command
AddOption(tenantIdOption);
AddOption(certificateNameOption);
AddOption(certificateThumbPrintOption);
+ AddOption(environmentOption);
AddOption(strategyOption);
this.SetHandler(async (context) =>
{
@@ -44,15 +47,16 @@ public sealed class LoginCommand : Command
var tenantId = context.ParseResult.GetValueForOption(tenantIdOption);
var certificateName = context.ParseResult.GetValueForOption(certificateNameOption);
var certificateThumbPrint = context.ParseResult.GetValueForOption(certificateThumbPrintOption);
+ var environment = context.ParseResult.GetValueForOption(environmentOption);
var strategy = context.ParseResult.GetValueForOption(strategyOption);
var cancellationToken = context.GetCancellationToken();
var authUtil = context.BindingContext.GetRequiredService();
var authSvcFactory = context.BindingContext.GetRequiredService();
- var authService = await authSvcFactory.GetAuthenticationServiceAsync(strategy, tenantId, clientId, certificateName, certificateThumbPrint, cancellationToken);
+ var authService = await authSvcFactory.GetAuthenticationServiceAsync(strategy, tenantId, clientId, certificateName, certificateThumbPrint, environment, cancellationToken);
await authService.LoginAsync(scopes, cancellationToken);
- await authUtil.SaveAuthenticationIdentifiersAsync(clientId, tenantId, certificateName, certificateThumbPrint, strategy, cancellationToken);
+ await authUtil.SaveAuthenticationIdentifiersAsync(clientId, tenantId, certificateName, certificateThumbPrint, strategy, environment, cancellationToken);
});
}
diff --git a/src/Microsoft.Graph.Cli.Core/Configuration/AuthenticationOptions.cs b/src/Microsoft.Graph.Cli.Core/Configuration/AuthenticationOptions.cs
index ad3cabac..d02868c2 100644
--- a/src/Microsoft.Graph.Cli.Core/Configuration/AuthenticationOptions.cs
+++ b/src/Microsoft.Graph.Cli.Core/Configuration/AuthenticationOptions.cs
@@ -8,7 +8,8 @@ namespace Microsoft.Graph.Cli.Core.Configuration;
public class AuthenticationOptions
{
///
- /// Authority
+ /// Entra authority. Corresponds to the via the
+ /// convenience extension.
///
public string? Authority { get; set; }
@@ -36,4 +37,10 @@ public class AuthenticationOptions
/// Authentication strategy
///
public AuthenticationStrategy Strategy { get; set; } = AuthenticationStrategy.DeviceCode;
+
+ ///
+ /// Cloud environment for authentication. This is stored separately from
+ /// Authority in case some environments use the same authority.
+ ///
+ public CloudEnvironment Environment { get; set; } = CloudEnvironment.Global;
}
diff --git a/src/Microsoft.Graph.Cli.Core/IO/AuthenticationCacheManager.cs b/src/Microsoft.Graph.Cli.Core/IO/AuthenticationCacheManager.cs
index 1c24eefd..2869cee6 100644
--- a/src/Microsoft.Graph.Cli.Core/IO/AuthenticationCacheManager.cs
+++ b/src/Microsoft.Graph.Cli.Core/IO/AuthenticationCacheManager.cs
@@ -54,13 +54,13 @@ public async Task ReadAuthenticationIdentifiersAsync(Canc
}
///
- public async Task SaveAuthenticationIdentifiersAsync(string? clientId, string? tenantId, string? certificateName, string? certificateThumbPrint, AuthenticationStrategy strategy, CancellationToken cancellationToken = default)
+ public async Task SaveAuthenticationIdentifiersAsync(string? clientId, string? tenantId, string? certificateName, string? certificateThumbPrint, AuthenticationStrategy strategy, CloudEnvironment environment = CloudEnvironment.Global, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
var path = this.GetAuthenticationCacheFilePath();
ConfigurationRoot configuration = await ReadConfigurationAsync(cancellationToken) ?? new Configuration.ConfigurationRoot();
var authOptions = configuration.AuthenticationOptions;
- var adAuthority = Constants.DefaultAuthority;
+ var adAuthority = environment.Authority();
clientId = clientId ?? Constants.DefaultAppId;
tenantId = tenantId ?? Constants.DefaultTenant;
@@ -68,17 +68,18 @@ public async Task SaveAuthenticationIdentifiersAsync(string? clientId, string? t
if (
clientId != authOptions.ClientId || tenantId != authOptions.TenantId || certificateName != authOptions.ClientCertificateName ||
certificateThumbPrint != authOptions.ClientCertificateThumbPrint || strategy != authOptions.Strategy ||
- adAuthority != authOptions.Authority
+ (authOptions.Authority is not null && adAuthority != new Uri(authOptions.Authority))
)
{
configuration.AuthenticationOptions = new AuthenticationOptions
{
- Authority = adAuthority,
+ Authority = adAuthority.ToString(),
ClientId = clientId,
TenantId = tenantId,
ClientCertificateName = certificateName,
ClientCertificateThumbPrint = certificateThumbPrint,
Strategy = strategy,
+ Environment = environment,
};
await WriteConfigurationAsync(path, configuration, cancellationToken);
@@ -183,18 +184,18 @@ private void DeleteAuthenticationRecord()
}
}
- private async Task WriteConfigurationAsync(string path, ConfigurationRoot configuration, CancellationToken cancellationToken = default, int retryCount = 0)
+ private async Task WriteConfigurationAsync(string path, ConfigurationRoot configuration, CancellationToken cancellationToken = default, int retryCount = 1)
{
try
{
- using FileStream fileStream = File.Open(path, FileMode.Create, FileAccess.Write);
+ using FileStream fileStream = File.Open(path, FileMode.Create, FileAccess.Write, FileShare.Read);
await JsonSerializer.SerializeAsync(fileStream, configuration, SourceGenerationContext.Default.ConfigurationRoot, cancellationToken: cancellationToken).ConfigureAwait(false);
}
catch (DirectoryNotFoundException)
{
Directory.CreateDirectory(path);
- if (retryCount < 1)
- await WriteConfigurationAsync(path, configuration, cancellationToken, retryCount + 1);
+ if (retryCount > 0)
+ await WriteConfigurationAsync(path, configuration, cancellationToken, retryCount - 1);
}
}
diff --git a/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs b/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs
index 2a1d3cff..f080f3ae 100644
--- a/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs
+++ b/src/Microsoft.Graph.Cli.Core/IO/GraphCliClientFactory.cs
@@ -23,12 +23,12 @@ public class GraphCliClientFactory
///
/// Graph client options
/// API version
- /// National cloud in use.
+ /// The cloud environment in use.
/// Final HTTP handler
/// Logging handler
/// Other middlewares.
/// Returns a new HTTP client.
- public static HttpClient GetDefaultClient(GraphClientOptions? options = null, string version = "v1.0", string nationalCloud = GraphClientFactory.Global_Cloud, HttpMessageHandler? finalHandler = null, LoggingHandler? loggingHandler = null, params DelegatingHandler[] middlewares)
+ public static HttpClient GetDefaultClient(GraphClientOptions? options = null, string version = "v1.0", CloudEnvironment environment = CloudEnvironment.Global, HttpMessageHandler? finalHandler = null, LoggingHandler? loggingHandler = null, params DelegatingHandler[] middlewares)
{
var m = new List();
@@ -67,6 +67,6 @@ public static HttpClient GetDefaultClient(GraphClientOptions? options = null, st
return 0;
});
- return GraphClientFactory.Create(version: version, nationalCloud: nationalCloud, finalHandler: finalHandler, handlers: m);
+ return GraphClientFactory.Create(version: version, nationalCloud: environment.GraphClientCloud(), finalHandler: finalHandler, handlers: m);
}
}
diff --git a/src/Microsoft.Graph.Cli.Core/IO/IAuthenticationCacheManager.cs b/src/Microsoft.Graph.Cli.Core/IO/IAuthenticationCacheManager.cs
index 71eacd3e..95a5dce0 100644
--- a/src/Microsoft.Graph.Cli.Core/IO/IAuthenticationCacheManager.cs
+++ b/src/Microsoft.Graph.Cli.Core/IO/IAuthenticationCacheManager.cs
@@ -25,9 +25,10 @@ public interface IAuthenticationCacheManager
/// Certificate name
/// Certificate thumb-print
/// Authentication strategy.
+ /// The cloud environment.
/// Cancellation token.
/// A void awaitable task.
- Task SaveAuthenticationIdentifiersAsync(string? clientId, string? tenantId, string? certificateName, string? certificateThumbPrint, AuthenticationStrategy strategy, CancellationToken cancellationToken = default);
+ Task SaveAuthenticationIdentifiersAsync(string? clientId, string? tenantId, string? certificateName, string? certificateThumbPrint, AuthenticationStrategy strategy, CloudEnvironment environment = CloudEnvironment.Global, CancellationToken cancellationToken = default);
///
/// Reads authentication options from the authentication cache path.
diff --git a/src/Microsoft.Graph.Cli.Core/utils/Constants.cs b/src/Microsoft.Graph.Cli.Core/utils/Constants.cs
index 7fda69d5..c38fbc64 100644
--- a/src/Microsoft.Graph.Cli.Core/utils/Constants.cs
+++ b/src/Microsoft.Graph.Cli.Core/utils/Constants.cs
@@ -5,7 +5,7 @@ namespace Microsoft.Graph.Cli.Core.Utils
///
/// Graph CLI Core Constants
///
- public class Constants
+ internal class Constants
{
///
/// Name of the CLI core directory in the APPDATA root.
@@ -37,15 +37,10 @@ public class Constants
///
public const string DefaultTenant = "common";
- ///
- /// Default authority
- ///
- public const string DefaultAuthority = "https://login.microsoftonline.com";
-
///
/// Environmrnt constants.
///
- public static class Environment
+ internal static class Environment
{
///
/// Tenant Id.
diff --git a/src/sample/Program.cs b/src/sample/Program.cs
index 412b4f56..a6373991 100644
--- a/src/sample/Program.cs
+++ b/src/sample/Program.cs
@@ -176,16 +176,17 @@ static IHostBuilder CreateHostBuilder(string[] args) =>
GraphServiceTargetVersion = "1.0"
};
+ var authSettings = p.GetRequiredService>().Value;
var headersHandler = new NativeHttpHeadersHandler(() => InMemoryHeadersStore.Instance, p.GetService>());
- return GraphCliClientFactory.GetDefaultClient(options, loggingHandler: p.GetRequiredService(), middlewares: new[] { headersHandler });
+ return GraphCliClientFactory.GetDefaultClient(options, environment: authSettings.Environment, loggingHandler: p.GetRequiredService(), middlewares: new[] { headersHandler });
});
services.AddSingleton(p =>
{
var authSettings = p.GetRequiredService>()?.Value;
var serviceFactory = p.GetRequiredService();
AuthenticationStrategy authStrategy = authSettings?.Strategy ?? AuthenticationStrategy.DeviceCode;
- var credential = serviceFactory.GetTokenCredentialAsync(authStrategy, authSettings?.TenantId, authSettings?.ClientId, authSettings?.ClientCertificateName, authSettings?.ClientCertificateThumbPrint);
+ var credential = serviceFactory.GetTokenCredentialAsync(authStrategy, authSettings?.TenantId, authSettings?.ClientId, authSettings?.ClientCertificateName, authSettings?.ClientCertificateThumbPrint, authSettings?.Environment ?? CloudEnvironment.Global);
credential.Wait();
return new AzureIdentityAuthenticationProvider(credential.Result);
});