Skip to content

Commit

Permalink
Add input parameter for Instance (#2400)
Browse files Browse the repository at this point in the history
  • Loading branch information
zahalzel authored May 9, 2023
1 parent 1f49f72 commit b0d26d3
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 38 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ namespace Microsoft.DotNet.MSIdentity.DeveloperCredentials
{
public class DeveloperCredentialsReader
{
public TokenCredential GetDeveloperCredentials(string? username, string? currentApplicationTenantId, IConsoleLogger consoleLogger)
public TokenCredential GetDeveloperCredentials(string? username, string? currentApplicationTenantId, string? instance, IConsoleLogger consoleLogger)
{
#if AzureSDK
* Tried but does not work if another tenant than the home tenant id is specified
Expand All @@ -30,6 +30,7 @@ public TokenCredential GetDeveloperCredentials(string? username, string? current
TokenCredential tokenCredential = new MsalTokenCredential(
currentApplicationTenantId,
username,
instance,
consoleLogger);
return tokenCredential;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,13 @@ public class MsalTokenCredential : TokenCredential
public MsalTokenCredential(
string? tenantId,
string? username,
string? instance,
IConsoleLogger consoleLogger)
{
_consoleLogger = consoleLogger;
TenantId = tenantId ?? "organizations"; // MSA-passthrough
Username = username;
Instance = "https://login.microsoftonline.com";
Instance = instance ?? "https://login.microsoftonline.com"; // default instance
}

private IPublicClientApplication? App { get; set; }
Expand Down Expand Up @@ -71,6 +72,7 @@ private async Task<IPublicClientApplication> GetOrCreateApp()
.Build();

App = PublicClientApplicationBuilder.Create(clientId)
.WithAuthority(Instance, TenantId)
.WithRedirectUri(RedirectUri)
.Build();

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@
<value>Failed to provision Client Application for Blazor WASM hosted project</value>
</data>
<data name="FailedToRetrieveADObjectsError" xml:space="preserve">
<value>Failed to retrieve all Azure AD/AD B2C objects(apps/service principals</value>
<value>Failed to retrieve all Azure AD/AD B2C objects (apps/service principals), exception: {0}</value>
<comment>0 = error message</comment>
</data>
<data name="FailedToRetrieveApplicationParameters" xml:space="preserve">
<value>Failed to retrieve application parameters.</value>
Expand Down Expand Up @@ -347,4 +348,4 @@
<data name="UpdatingProjectPackages" xml:space="preserve">
<value>Updating project packages ...</value>
</data>
</root>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,7 @@ internal static TokenCredential GetTokenCredential(ProvisioningToolOptions provi
return developerCredentialsReader.GetDeveloperCredentials(
provisioningToolOptions.Username,
currentApplicationTenantId ?? provisioningToolOptions.TenantId,
provisioningToolOptions.Instance,
consoleLogger);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,17 +65,17 @@ public GraphObjectRetriever(GraphServiceClient graphServiceClient, IConsoleLogge
nextPage = null;
}
}
catch (ServiceException)
catch (ServiceException se)
{
nextPage = null;
_consoleLogger.LogFailureAndExit(Resources.FailedToRetrieveADObjectsError);
_consoleLogger.LogFailureAndExit(string.Format(Resources.FailedToRetrieveADObjectsError, se.Message));
}
}
}
}
catch (ServiceException)
catch (ServiceException se)
{
_consoleLogger.LogFailureAndExit(Resources.FailedToRetrieveADObjectsError);
_consoleLogger.LogFailureAndExit(string.Format(Resources.FailedToRetrieveADObjectsError, se.Message));
}

return graphObjectsList;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public MsAADTool(string commandName, ProvisioningToolOptions provisioningToolOpt
ProvisioningToolOptions = provisioningToolOptions;
CommandName = commandName;
ConsoleLogger = new ConsoleLogger(CommandName, ProvisioningToolOptions.Json);
TokenCredential = new MsalTokenCredential(ProvisioningToolOptions.TenantId, ProvisioningToolOptions.Username, ConsoleLogger);
TokenCredential = new MsalTokenCredential(ProvisioningToolOptions.TenantId, ProvisioningToolOptions.Username, ProvisioningToolOptions.Instance, ConsoleLogger);
GraphServiceClient = new GraphServiceClient(new TokenCredentialAuthenticationProvider(TokenCredential));
AzureManagementAPI = new AzureManagementAuthenticationProvider(TokenCredential);
GraphObjectRetriever = new GraphObjectRetriever(GraphServiceClient, ConsoleLogger);
Expand Down Expand Up @@ -91,13 +91,9 @@ internal async Task<string> PrintApplicationsList()

internal async Task<IList<Application>> GetApplicationsAsync()
{
var graphObjectsList = await GraphObjectRetriever.GetGraphObjects();
if (graphObjectsList is null)
{
ConsoleLogger.LogFailureAndExit(Resources.FailedToRetrieveADObjectsError);
}

IList<Application> applicationList = new List<Application>();

var graphObjectsList = await GraphObjectRetriever.GetGraphObjects(); // Will exit early if call fails
foreach (var graphObj in graphObjectsList!)
{
if (graphObj is Application app)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,12 @@ public string ProjectTypeIdentifier
/// </summary>
public string? TenantId { get; set; }

/// <summary>
/// URL that indicates a directory that MSAL can request tokens from.
/// e.g. https://login.microsoftonline.com/, https://login.microsoftonline.us/
/// </summary>
public string? Instance { get; set; }

/// <summary>
/// Required for the creation of a B2C application.
/// Represents the sign-up/sign-in user flow.
Expand Down
46 changes: 28 additions & 18 deletions tools/dotnet-msidentity/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ public static async Task<int> Main(string[] args)
ApiClientIdOption,
SusiPolicyIdOption,
TenantOption,
UsernameOption);
UsernameOption,
InstanceOption);

//internal commands
var listAadAppsCommand = ListAADAppsCommand();
Expand Down Expand Up @@ -191,77 +192,77 @@ internal static async Task<int> HandleClientSecrets(ProvisioningToolOptions prov
}

internal static RootCommand MsIdentityCommand() =>
new RootCommand(
new(
description: "Creates or updates an Azure AD / Azure AD B2C application, and updates the project, using your developer credentials (from Visual Studio, Azure CLI, Azure RM PowerShell, VS Code).\n")
{
};

internal static Command ListAADAppsCommand() =>
new Command(
new(
name: Commands.LIST_AAD_APPS_COMMAND,
description: "Lists AAD Applications for a given tenant/username.\n")
{
TenantOption, UsernameOption, JsonOption
TenantOption, UsernameOption, InstanceOption, JsonOption
};

internal static Command ListServicePrincipalsCommand() =>
new Command(
new(
name: Commands.LIST_SERVICE_PRINCIPALS_COMMAND,
description: "Lists AAD Service Principals.\n")
{
TenantOption, UsernameOption, JsonOption
TenantOption, UsernameOption, InstanceOption, JsonOption
};

internal static Command ListTenantsCommand() =>
new Command(
new(
name: Commands.LIST_TENANTS_COMMAND,
description: "Lists AAD and AAD B2C tenants for a given user.\n")
{
UsernameOption, JsonOption
};

internal static Command CreateClientSecretCommand() =>
new Command(
new(
name: Commands.ADD_CLIENT_SECRET,
description: "Create client secret for an Azure AD or AD B2C app registration.\n")
{
TenantOption, UsernameOption, JsonOption, ClientIdOption, ProjectFilePathOption, UpdateUserSecretsOption
TenantOption, UsernameOption, InstanceOption, JsonOption, ClientIdOption, ProjectFilePathOption, UpdateUserSecretsOption
};

internal static Command RegisterApplicationCommand() =>
new Command(
new(
name: Commands.REGISTER_APPLICATIION_COMMAND,
description: "Register an Azure AD or Azure AD B2C app registration in Azure and update the project." +
"\n\t- Updates the appsettings.json file.\n")
{
TenantOption, UsernameOption, JsonOption, ClientIdOption, ClientSecretOption, HostedAppIdUriOption, ApiClientIdOption, SusiPolicyIdOption, ProjectFilePathOption
TenantOption, UsernameOption, InstanceOption, JsonOption, ClientIdOption, ClientSecretOption, HostedAppIdUriOption, ApiClientIdOption, SusiPolicyIdOption, ProjectFilePathOption
};

internal static Command UpdateProjectCommand() =>
new Command(
new(
name: Commands.UPDATE_PROJECT_COMMAND,
description: "Update an Azure AD/AD B2C app registration in Azure and the project." +
"\n\t- Updates the appsettings.json file." +
"\n\t- Updates the Startup.cs file." +
"\n\t- Updates the user secrets.\n")
{
TenantOption, UsernameOption, ClientIdOption, JsonOption, ProjectFilePathOption, ConfigUpdateOption, CodeUpdateOption, PackagesUpdateOption, CallsGraphOption, CallsDownstreamApiOption, UpdateUserSecretsOption, RedirectUriOption, SusiPolicyIdOption
TenantOption, UsernameOption, InstanceOption, ClientIdOption, JsonOption, ProjectFilePathOption, ConfigUpdateOption, CodeUpdateOption, PackagesUpdateOption, CallsGraphOption, CallsDownstreamApiOption, UpdateUserSecretsOption, RedirectUriOption, SusiPolicyIdOption
};

internal static Command UpdateAppRegistrationCommand() =>
new Command(
new(
name: Commands.UPDATE_APP_REGISTRATION_COMMAND,
description: "Update an Azure AD/AD B2C app registration in Azure.\n")
{
TenantOption, UsernameOption, JsonOption, HostedAppIdUriOption, ClientIdOption, RedirectUriOption, EnableIdTokenOption, EnableAccessToken, ClientProjectOption, ApiScopesOption
TenantOption, UsernameOption, InstanceOption, JsonOption, HostedAppIdUriOption, ClientIdOption, RedirectUriOption, EnableIdTokenOption, EnableAccessToken, ClientProjectOption, ApiScopesOption
};

internal static Command CreateAppRegistrationCommand() =>
new Command(
new(
name: Commands.CREATE_APP_REGISTRATION_COMMAND,
description: "Create an Azure AD/AD B2C app registration in Azure.\n")
{
TenantOption, UsernameOption, JsonOption, AppDisplayName, ProjectFilePathOption, ProjectType, ClientProjectOption
TenantOption, UsernameOption, InstanceOption, JsonOption, AppDisplayName, ProjectFilePathOption, ProjectType, ClientProjectOption
};

internal static Command UnregisterApplicationCommand() =>
Expand All @@ -271,7 +272,7 @@ internal static Command UnregisterApplicationCommand() =>
description: "Unregister an Azure AD or Azure AD B2C app registration in Azure." +
"\n\t- Updates the appsettings.json file.\n")
{
TenantOption, UsernameOption, JsonOption, HostedAppIdUriOption, ProjectFilePathOption, ClientIdOption
TenantOption, UsernameOption, InstanceOption, JsonOption, HostedAppIdUriOption, ProjectFilePathOption, ClientIdOption
};

internal static Option<bool> JsonOption { get; } =
Expand Down Expand Up @@ -457,5 +458,14 @@ internal static Command UnregisterApplicationCommand() =>
{
IsRequired = false
};

internal static Option<string> InstanceOption { get; } =
new(
aliases: new[] { "-i", "--instance" },
description: "Instance where the Azure AD or Azure AD B2C tenant is located.\n" +
"If not specified, will default to https://login.microsoftonline.com/")
{
IsRequired = false
};
}
}
9 changes: 6 additions & 3 deletions tools/dotnet-msidentity/ProvisioningToolOptionsBinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ internal class ProvisioningToolOptionsBinder : BinderBase<ProvisioningToolOption
private readonly Option<string> _susiPolicyIdOption;
private readonly Option<string> _tenantOption;
private readonly Option<string> _usernameOption;
private readonly Option<string> _instanceOption;

public ProvisioningToolOptionsBinder(
Option<bool> jsonOption,
Expand All @@ -58,7 +59,8 @@ public ProvisioningToolOptionsBinder(
Option<string> apiClientIdOption,
Option<string> susiPolicyIdOption,
Option<string> tenantOption,
Option<string> usernameOption)
Option<string> usernameOption,
Option<string> instanceOption)
{
_jsonOption = jsonOption;
_enableIdTokenOption = enableIdTokenOption;
Expand All @@ -82,14 +84,14 @@ public ProvisioningToolOptionsBinder(
_susiPolicyIdOption = susiPolicyIdOption;
_tenantOption = tenantOption;
_usernameOption = usernameOption;
_instanceOption = instanceOption;
}

protected override ProvisioningToolOptions GetBoundValue(BindingContext bindingContext)
{
IList<string> redirectUriList = bindingContext.ParseResult.GetValue(_redirectUriOption) ?? new List<string>();
return new ProvisioningToolOptions
{

HostedApiScopes = bindingContext.ParseResult.GetValue(_hostedAppIdUriOption),
CallsDownstreamApi = bindingContext.ParseResult.GetValue(_callsDownstreamApiOption),
UpdateUserSecrets = bindingContext.ParseResult.GetValue(_updateUserSecretsOption),
Expand All @@ -112,7 +114,8 @@ protected override ProvisioningToolOptions GetBoundValue(BindingContext bindingC
CodeUpdate = bindingContext.ParseResult.GetValue(_codeUpdateOption),
PackagesUpdate = bindingContext.ParseResult.GetValue(_packagesUpdateOption),
ApiScopes = bindingContext.ParseResult.GetValue(_apiScopesOption),
ClientProject = bindingContext.ParseResult.GetValue(_clientProjectOption)
ClientProject = bindingContext.ParseResult.GetValue(_clientProjectOption),
Instance = bindingContext.ParseResult.GetValue(_instanceOption)
};
}
}
Expand Down
3 changes: 2 additions & 1 deletion tools/dotnet-scaffold/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ public static int Main(string[] args)
MsIdentity.ApiClientIdOption,
MsIdentity.SusiPolicyIdOption,
MsIdentity.TenantOption,
MsIdentity.UsernameOption);
MsIdentity.UsernameOption,
MsIdentity.InstanceOption);

//internal commands
var listAadAppsCommand = MsIdentity.ListAADAppsCommand();
Expand Down

0 comments on commit b0d26d3

Please sign in to comment.