diff --git a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/AuthenticationParameters/ApplicationParameters.cs b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/AuthenticationParameters/ApplicationParameters.cs
index 4d2431f54..da6ef6ae1 100644
--- a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/AuthenticationParameters/ApplicationParameters.cs
+++ b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/AuthenticationParameters/ApplicationParameters.cs
@@ -107,17 +107,17 @@ public string? Domain1
///
/// The project is a web API.
///
- public bool IsWebApi { get; set; }
+ public bool? IsWebApi { get; set; }
///
/// The project is a web app.
///
- public bool IsWebApp { get; set; }
+ public bool? IsWebApp { get; set; }
///
/// The project is a blazor web assembly.
///
- public bool IsBlazorWasm { get; set; }
+ public bool? IsBlazorWasm { get; set; }
///
/// The app calls Microsoft Graph.
diff --git a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/CodeReaderWriter/CodeReader.cs b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/CodeReaderWriter/CodeReader.cs
index 0461f2c3e..3ccb53fb2 100644
--- a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/CodeReaderWriter/CodeReader.cs
+++ b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/CodeReaderWriter/CodeReader.cs
@@ -74,8 +74,10 @@ private static void ProcessProject(
private static void PostProcessWebUris(ProjectAuthenticationSettings projectAuthenticationSettings)
{
- bool isBlazorWasm = projectAuthenticationSettings.ApplicationParameters.IsBlazorWasm
- && !projectAuthenticationSettings.ApplicationParameters.IsWebApp;
+ bool isBlazorWasm = projectAuthenticationSettings.ApplicationParameters.IsBlazorWasm.HasValue &&
+ projectAuthenticationSettings.ApplicationParameters.IsBlazorWasm.Value &&
+ projectAuthenticationSettings.ApplicationParameters.IsWebApp.HasValue &&
+ !projectAuthenticationSettings.ApplicationParameters.IsWebApp.Value;
string callbackPath = projectAuthenticationSettings.ApplicationParameters.CallbackPath ?? "/signin-oidc";
if (isBlazorWasm)
{
diff --git a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/CodeReaderWriter/CodeWriter.cs b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/CodeReaderWriter/CodeWriter.cs
index 8f37015fd..b3bd02660 100644
--- a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/CodeReaderWriter/CodeWriter.cs
+++ b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/CodeReaderWriter/CodeWriter.cs
@@ -2,18 +2,18 @@
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.IO;
using System.Linq;
using Microsoft.DotNet.MSIdentity.AuthenticationParameters;
using Microsoft.DotNet.MSIdentity.Project;
+using Microsoft.DotNet.MSIdentity.Tool;
using Microsoft.Extensions.Internal;
namespace Microsoft.DotNet.MSIdentity.CodeReaderWriter
{
public static class CodeWriter
{
- internal static void WriteConfiguration(Summary summary, IEnumerable replacements, ApplicationParameters reconciledApplicationParameters, bool jsonOutput)
+ internal static void WriteConfiguration(Summary summary, IEnumerable replacements, ApplicationParameters reconciledApplicationParameters, IConsoleLogger consoleLogger)
{
foreach (var replacementsInFile in replacements.GroupBy(r => r.FilePath))
{
@@ -23,7 +23,7 @@ internal static void WriteConfiguration(Summary summary, IEnumerable r.Index))
{
- string? replaceBy = ComputeReplacement(r.ReplaceBy, reconciledApplicationParameters, jsonOutput);
+ string? replaceBy = ComputeReplacement(r.ReplaceBy, reconciledApplicationParameters, consoleLogger);
if (replaceBy != null && replaceBy!=r.ReplaceFrom)
{
int index = fileContent.IndexOf(r.ReplaceFrom /*, r.Index*/);
@@ -51,16 +51,16 @@ internal static void WriteConfiguration(Summary summary, IEnumerable();
var output = new List();
@@ -75,11 +75,7 @@ public static void InitUserSecrets(string projectPath, bool jsonOutput)
}
arguments.Add("init");
-
- if (!jsonOutput)
- {
- Console.Write("\nInitializing User Secrets . . . ");
- }
+ consoleLogger.LogMessage("\nInitializing User Secrets . . . ", LogMessageType.Error);
var result = Command.CreateDotNet(
"user-secrets",
@@ -90,22 +86,16 @@ public static void InitUserSecrets(string projectPath, bool jsonOutput)
if (result.ExitCode != 0)
{
- if (!jsonOutput)
- {
- Console.Write("FAILED\n");
- }
+ consoleLogger.LogMessage("FAILED\n", LogMessageType.Error, removeNewLine: true);
throw new Exception("Error while running dotnet-user-secrets init");
}
else
{
- if (!jsonOutput)
- {
- Console.Write("SUCCESS\n");
- }
+ consoleLogger.LogMessage("SUCCESS\n", removeNewLine: true);
}
}
- public static void AddPackage(string packageName, string packageVersion, string tfm, bool jsonOutput)
+ public static void AddPackage(string packageName, string packageVersion, string tfm, IConsoleLogger consoleLogger)
{
if (!string.IsNullOrEmpty(packageName) && ((!string.IsNullOrEmpty(packageVersion)) || (!string.IsNullOrEmpty(tfm))))
{
@@ -130,10 +120,8 @@ public static void AddPackage(string packageName, string packageVersion, string
arguments.Add("-f");
arguments.Add(tfm);
}
- if (!jsonOutput)
- {
- Console.Write($"\nAdding package {packageName} . . . ");
- }
+
+ consoleLogger.LogMessage($"\nAdding package {packageName} . . . ");
var result = Command.CreateDotNet(
"add",
@@ -144,19 +132,12 @@ public static void AddPackage(string packageName, string packageVersion, string
if (result.ExitCode != 0)
{
- if (!jsonOutput)
- {
- Console.Write("FAILED\n");
- Console.WriteLine($"Failed to add package {packageName}");
- }
+ consoleLogger.LogMessage("FAILED\n", removeNewLine: true);
+ consoleLogger.LogMessage($"Failed to add package {packageName}");
}
else
{
- if (!jsonOutput)
- {
- Console.Write("SUCCESS\n");
- }
-
+ consoleLogger.LogMessage("SUCCESS\n");
}
}
}
@@ -166,7 +147,7 @@ private static bool IsTfmPreRelease(string tfm)
return tfm.Equals("net6.0", StringComparison.OrdinalIgnoreCase);
}
- private static void SetUserSecerets(string projectPath, string key, string value, bool jsonOutput)
+ private static void SetUserSecerets(string projectPath, string key, string value, IConsoleLogger consoleLogger)
{
var errors = new List();
var output = new List();
@@ -196,14 +177,11 @@ private static void SetUserSecerets(string projectPath, string key, string value
}
else
{
- if (!jsonOutput)
- {
- Console.WriteLine($"\nAdded {key} to user secrets.\n");
- }
+ consoleLogger.LogMessage($"\nAdded {key} to user secrets.\n");
}
}
- private static string? ComputeReplacement(string replaceBy, ApplicationParameters reconciledApplicationParameters, bool jsonOutput)
+ private static string? ComputeReplacement(string replaceBy, ApplicationParameters reconciledApplicationParameters, IConsoleLogger consoleLogger)
{
string? replacement = replaceBy;
switch(replaceBy)
@@ -212,7 +190,7 @@ private static void SetUserSecerets(string projectPath, string key, string value
string? password = reconciledApplicationParameters.PasswordCredentials.LastOrDefault();
if (!string.IsNullOrEmpty(reconciledApplicationParameters.SecretsId) && !string.IsNullOrEmpty(password))
{
- AddUserSecrets(reconciledApplicationParameters.IsB2C, reconciledApplicationParameters.ProjectPath ?? string.Empty, password, jsonOutput);
+ AddUserSecrets(reconciledApplicationParameters.IsB2C, reconciledApplicationParameters.ProjectPath ?? string.Empty, password, consoleLogger);
}
else
{
diff --git a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/MicrosoftIdentityPlatform/MicrosoftIdentityPlatformApplicationManager.cs b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/MicrosoftIdentityPlatform/MicrosoftIdentityPlatformApplicationManager.cs
index b06404044..04aaf9bb9 100644
--- a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/MicrosoftIdentityPlatform/MicrosoftIdentityPlatformApplicationManager.cs
+++ b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/MicrosoftIdentityPlatform/MicrosoftIdentityPlatformApplicationManager.cs
@@ -19,16 +19,20 @@ public class MicrosoftIdentityPlatformApplicationManager
GraphServiceClient? _graphServiceClient;
- internal async Task CreateNewApp(
+ internal async Task CreateNewAppAsync(
TokenCredential tokenCredential,
ApplicationParameters applicationParameters,
- bool jsonOutput)
+ IConsoleLogger consoleLogger,
+ string commandName)
{
var graphServiceClient = GetGraphServiceClient(tokenCredential);
// Get the tenant
Organization? tenant = await GetTenant(graphServiceClient);
-
+ if (tenant != null && tenant.TenantType.Equals("AAD B2C", StringComparison.OrdinalIgnoreCase))
+ {
+ applicationParameters.IsB2C = true;
+ }
// Create the app.
Application application = new Application()
{
@@ -37,7 +41,7 @@ internal async Task CreateNewApp(
Description = applicationParameters.Description
};
- if (applicationParameters.IsWebApi)
+ if (applicationParameters.IsWebApi.GetValueOrDefault())
{
application.Api = new ApiApplication()
{
@@ -45,11 +49,11 @@ internal async Task CreateNewApp(
};
}
- if (applicationParameters.IsWebApp)
+ if (applicationParameters.IsWebApp.GetValueOrDefault())
{
AddWebAppPlatform(applicationParameters, application);
}
- else if (applicationParameters.IsBlazorWasm)
+ else if (applicationParameters.IsBlazorWasm.GetValueOrDefault())
{
// In .NET Core 3.1, Blazor uses MSAL.js 1.x (web redirect URIs)
// whereas in .NET 5.0, Blazor uses MSAL.js 2.x (SPA redirect URIs)
@@ -96,14 +100,14 @@ await AddAdminConsentToApiPermissions(
// For web API, we need to know the appId of the created app to compute the Identifier URI,
// and therefore we need to do it after the app is created (updating the app)
- if (applicationParameters.IsWebApi
+ if (applicationParameters.IsWebApi.GetValueOrDefault()
&& createdApplication.Api != null
&& (createdApplication.IdentifierUris == null || !createdApplication.IdentifierUris.Any()))
{
await ExposeScopes(graphServiceClient, createdApplication);
// Blazorwasm hosted: add permission to server web API from client SPA
- if (applicationParameters.IsBlazorWasm)
+ if (applicationParameters.IsBlazorWasm.GetValueOrDefault())
{
await AddApiPermissionFromBlazorwasmHostedSpaToServerApi(
graphServiceClient,
@@ -112,25 +116,39 @@ await AddApiPermissionFromBlazorwasmHostedSpaToServerApi(
applicationParameters.IsB2C);
}
}
-
+ ApplicationParameters? effectiveApplicationParameters = null;
// Re-reading the app to be sure to have everything.
createdApplication = (await graphServiceClient.Applications
.Request()
.Filter($"appId eq '{createdApplication.AppId}'")
.GetAsync()).First();
- var effectiveApplicationParameters = GetEffectiveApplicationParameters(tenant!, createdApplication, applicationParameters);
+ //log json console message here since we need the Microsoft.Graph.Application
+ JsonResponse jsonResponse = new JsonResponse(commandName);
+ if (createdApplication != null)
+ {
+ jsonResponse.State = State.Success;
+ jsonResponse.Content = createdApplication;
+ effectiveApplicationParameters = GetEffectiveApplicationParameters(tenant!, createdApplication, applicationParameters);
- // Add password credentials
- if (applicationParameters.CallsMicrosoftGraph || applicationParameters.CallsDownstreamApi)
+ // Add password credentials
+ if (applicationParameters.CallsMicrosoftGraph || applicationParameters.CallsDownstreamApi)
+ {
+ await AddPasswordCredentialsAsync(
+ graphServiceClient,
+ createdApplication.Id,
+ effectiveApplicationParameters,
+ consoleLogger);
+ }
+
+ }
+ else
{
- await AddPasswordCredentials(
- graphServiceClient,
- createdApplication.Id,
- effectiveApplicationParameters,
- jsonOutput);
+ jsonResponse.State = State.Fail;
+ jsonResponse.Content = "Failed to create Azure AD/AD B2C app registration";
+ consoleLogger.LogJsonMessage(jsonResponse);
}
-
+ consoleLogger.LogJsonMessage(jsonResponse);
return effectiveApplicationParameters;
}
@@ -166,18 +184,20 @@ await AddPasswordCredentials(
return tenant;
}
- internal async Task UpdateApplication(TokenCredential tokenCredential, ApplicationParameters? reconcialedApplicationParameters, ProvisioningToolOptions toolOptions)
+ internal async Task UpdateApplication(TokenCredential tokenCredential, ApplicationParameters? reconciledApplicationParameters, ProvisioningToolOptions toolOptions)
{
bool updateStatus = false;
- if (reconcialedApplicationParameters != null)
+ if (reconciledApplicationParameters != null)
{
var graphServiceClient = GetGraphServiceClient(tokenCredential);
var existingApplication = (await graphServiceClient.Applications
.Request()
- .Filter($"appId eq '{reconcialedApplicationParameters.ClientId}'")
+ .Filter($"appId eq '{reconciledApplicationParameters.ClientId}'")
.GetAsync()).First();
+ bool needsUpdate = false;
+
// Updates the redirect URIs
if (existingApplication.Web == null)
{
@@ -192,44 +212,55 @@ internal async Task UpdateApplication(TokenCredential tokenCredential, App
//update redirect uris
List existingRedirectUris = updatedApp.Web.RedirectUris.ToList();
List urisToEnsure = ValidateUris(toolOptions.RedirectUris).ToList();
+ int originalUrisCount = existingRedirectUris.Count;
existingRedirectUris.AddRange(urisToEnsure);
updatedApp.Web.RedirectUris = existingRedirectUris.Distinct();
-
- //update implicit grant settings
+ if (updatedApp.Web.RedirectUris.Count() > originalUrisCount)
+ {
+ needsUpdate = true;
+ }
+
if (updatedApp.Web.ImplicitGrantSettings == null)
{
updatedApp.Web.ImplicitGrantSettings = new ImplicitGrantSettings();
}
- if (toolOptions.EnableAccessToken.HasValue)
+ //update implicit grant settings if need be.
+ if (toolOptions.EnableAccessToken.HasValue && (toolOptions.EnableAccessToken.Value != updatedApp.Web.ImplicitGrantSettings.EnableAccessTokenIssuance))
{
+ needsUpdate = true;
updatedApp.Web.ImplicitGrantSettings.EnableAccessTokenIssuance = toolOptions.EnableAccessToken.Value;
}
- if (toolOptions.EnableIdToken.HasValue)
+ if (toolOptions.EnableIdToken.HasValue && (toolOptions.EnableIdToken.Value != updatedApp.Web.ImplicitGrantSettings.EnableIdTokenIssuance))
{
+ needsUpdate = true;
updatedApp.Web.ImplicitGrantSettings.EnableIdTokenIssuance = toolOptions.EnableIdToken.Value;
}
+
- // TODO: update other fields.
- // See https://github.com/jmprieur/app-provisonning-tool/issues/10
- try
- {
- await graphServiceClient.Applications[existingApplication.Id]
- .Request()
- .UpdateAsync(updatedApp).ConfigureAwait(false);
- updateStatus = true;
- }
- //TODO update exception
- catch (Exception)
+ if (needsUpdate)
{
+ try
+ {
+ // TODO: update other fields.
+ // See https://github.com/jmprieur/app-provisonning-tool/issues/10
+ await graphServiceClient.Applications[existingApplication.Id]
+ .Request()
+ .UpdateAsync(updatedApp).ConfigureAwait(false);
+ updateStatus = true;
+ }
+ //TODO update exception
+ catch (ServiceException)
+ {
+ updateStatus = false;
+ }
}
}
return updateStatus;
}
//checks for valid https uris.
- //TODO Unit test
internal static IList ValidateUris(IList redirectUris)
{
IList validUris = new List();
@@ -301,11 +332,11 @@ await graphServiceClient.Oauth2PermissionGrants
///
///
///
- internal static async Task AddPasswordCredentials(
+ internal static async Task AddPasswordCredentialsAsync(
GraphServiceClient graphServiceClient,
string applicatonId,
ApplicationParameters effectiveApplicationParameters,
- bool jsonOutput)
+ IConsoleLogger consoleLogger)
{
string? password = string.Empty;
var passwordCredential = new PasswordCredential
@@ -326,10 +357,7 @@ internal static async Task AddPasswordCredentials(
}
catch (ServiceException se)
{
- if (!jsonOutput)
- {
- Console.Error.WriteLine($"Failed to create password : {se.Error.Message}");
- }
+ consoleLogger.LogMessage($"Failed to create password : {se.Error.Message}", LogMessageType.Error);
}
}
return password;
@@ -485,7 +513,8 @@ private static void AddWebAppPlatform(ApplicationParameters applicationParameter
// Explicit usage of MicrosoftGraph openid and offline_access, in the case
// of Azure AD B2C.
- if (applicationParameters.IsB2C && applicationParameters.IsWebApp || applicationParameters.IsBlazorWasm)
+ if (applicationParameters.IsB2C && (applicationParameters.IsWebApp.HasValue && applicationParameters.IsWebApp.Value)
+ || (applicationParameters.IsBlazorWasm.HasValue && applicationParameters.IsBlazorWasm.Value))
{
if (applicationParameters.CalledApiScopes == null)
{
@@ -588,25 +617,33 @@ private string AppParameterAudienceToMicrosoftIdentityPlatformAppAudience(string
};
}
- internal async Task Unregister(TokenCredential tokenCredential, ApplicationParameters applicationParameters)
+ internal async Task UnregisterAsync(TokenCredential tokenCredential, ApplicationParameters applicationParameters)
{
+ bool unregisterSuccess = false;
var graphServiceClient = GetGraphServiceClient(tokenCredential);
- var apps = await graphServiceClient.Applications
- .Request()
- .Filter($"appId eq '{applicationParameters.ClientId}'")
- .GetAsync();
+ var readApplication = (await graphServiceClient.Applications
+ .Request()
+ .Filter($"appId eq '{applicationParameters.ClientId}'")
+ .GetAsync()).FirstOrDefault();
- var readApplication = apps.FirstOrDefault();
if (readApplication != null)
{
- var clientId = readApplication.Id;
- await graphServiceClient.Applications[$"{readApplication.Id}"]
- .Request()
- .DeleteAsync();
-
- Console.WriteLine($"Unregistered the Azure AD w/ client id = {clientId}\n");
+ try
+ {
+ var clientId = readApplication.Id;
+ await graphServiceClient.Applications[$"{readApplication.Id}"]
+ .Request()
+ .DeleteAsync();
+ unregisterSuccess = true;
+ }
+ catch (ServiceException)
+ {
+ unregisterSuccess = false;
+ }
}
+
+ return unregisterSuccess;
}
internal GraphServiceClient GetGraphServiceClient(TokenCredential tokenCredential)
diff --git a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/AppProvisioningTool.cs b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/AppProvisioningTool.cs
index 60dac2b87..143aaeb1c 100644
--- a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/AppProvisioningTool.cs
+++ b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/AppProvisioningTool.cs
@@ -4,10 +4,8 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
-using System.Text.Json;
using System.Threading.Tasks;
using Azure.Core;
-using Microsoft.CodeAnalysis;
using Microsoft.DotNet.MSIdentity.Properties;
using Microsoft.DotNet.MSIdentity.AuthenticationParameters;
using Microsoft.DotNet.MSIdentity.CodeReaderWriter;
@@ -15,7 +13,6 @@
using Microsoft.DotNet.MSIdentity.MicrosoftIdentityPlatformApplication;
using Microsoft.DotNet.MSIdentity.Project;
using Microsoft.DotNet.MSIdentity.Tool;
-using Microsoft.Graph;
using Newtonsoft.Json.Linq;
using Directory = System.IO.Directory;
using File = System.IO.File;
@@ -28,6 +25,7 @@ namespace Microsoft.DotNet.MSIdentity
///
public class AppProvisioningTool : IMsAADTool
{
+ internal IConsoleLogger ConsoleLogger { get; }
private ProvisioningToolOptions ProvisioningToolOptions { get; set; }
private string CommandName { get; }
@@ -40,6 +38,7 @@ public AppProvisioningTool(string commandName, ProvisioningToolOptions provision
{
CommandName = commandName;
ProvisioningToolOptions = provisioningToolOptions;
+ ConsoleLogger = new ConsoleLogger(ProvisioningToolOptions.Json);
}
public async Task Run()
@@ -50,11 +49,25 @@ public AppProvisioningTool(string commandName, ProvisioningToolOptions provision
var csProjfiles = Directory.EnumerateFiles(ProvisioningToolOptions.ProjectPath, "*.csproj");
if (csProjfiles.Any())
{
+ if (csProjfiles.Count() > 1)
+ {
+ string errorMsg = "Specify one .csproj file for the --project-path";
+ ConsoleLogger.LogJsonMessage(new JsonResponse(CommandName, State.Fail, errorMsg));
+ ConsoleLogger.LogMessage(errorMsg, LogMessageType.Error);
+ return null;
+ }
var filePath = csProjfiles.First();
ProvisioningToolOptions.ProjectFilePath = filePath;
}
}
+ string currentDirectory = Directory.GetCurrentDirectory();
+ //if its current directory, update it using the ProjectPath
+ if (ProvisioningToolOptions.ProjectPath.Equals(currentDirectory, StringComparison.OrdinalIgnoreCase))
+ {
+ ProvisioningToolOptions.ProjectPath = Path.GetDirectoryName(ProvisioningToolOptions.ProjectFilePath) ?? currentDirectory;
+ }
+
//get appsettings.json file path
var appSettingsFile = Directory.EnumerateFiles(ProvisioningToolOptions.ProjectPath, "appsettings.json");
if (appSettingsFile.Any())
@@ -63,9 +76,23 @@ public AppProvisioningTool(string commandName, ProvisioningToolOptions provision
ProvisioningToolOptions.AppSettingsFilePath = filePath;
}
+ ProjectDescription? projectDescription = ProjectDescriptionReader.GetProjectDescription(
+ ProvisioningToolOptions.ProjectTypeIdentifier,
+ ProvisioningToolOptions.ProjectPath);
+
+ if (projectDescription == null)
+ {
+ ConsoleLogger.LogMessage($"No project found in {ProvisioningToolOptions.ProjectPath}.", LogMessageType.Error);
+ }
+ else
+ {
+ ConsoleLogger.LogMessage($"Detected project type {projectDescription.Identifier}.");
+ }
+
ProjectAuthenticationSettings projectSettings = InferApplicationParameters(
ProvisioningToolOptions,
- ProjectDescriptionReader.projectDescriptions);
+ ProjectDescriptionReader.projectDescriptions,
+ projectDescription);
// Get developer credentials
TokenCredential tokenCredential = GetTokenCredential(
@@ -76,51 +103,17 @@ public AppProvisioningTool(string commandName, ProvisioningToolOptions provision
//TODO: switch case to handle all the different commands.
ApplicationParameters? applicationParameters = null;
- switch (CommandName)
- {
- case Commands.UPDATE_PROJECT_COMMAND:
- applicationParameters = await ReadMicrosoftIdentityApplication(tokenCredential, projectSettings.ApplicationParameters);
- await UpdateProject(tokenCredential, applicationParameters);
- return applicationParameters;
-
- case Commands.UPDATE_APPLICATION_COMMAND:
- applicationParameters = await ReadMicrosoftIdentityApplication(tokenCredential, projectSettings.ApplicationParameters);
- await UpdateApplication(tokenCredential, applicationParameters);
- return applicationParameters;
-
- case Commands.UNREGISTER_APPLICATION_COMMAND:
- await UnregisterApplication(tokenCredential, projectSettings.ApplicationParameters);
- return null;
-
- case Commands.ADD_CLIENT_SECRET:
- applicationParameters = await ReadMicrosoftIdentityApplication(tokenCredential, projectSettings.ApplicationParameters);
- await AddClientSecret(tokenCredential, applicationParameters);
- return applicationParameters;
-
- }
- // If needed, infer project type from code
- ProjectDescription? projectDescription = ProjectDescriptionReader.GetProjectDescription(
- ProvisioningToolOptions.ProjectTypeIdentifier,
- ProvisioningToolOptions.ProjectPath);
-
- if (projectDescription == null)
- {
- Console.WriteLine($"The code in {ProvisioningToolOptions.ProjectPath} wasn't recognized as supported by the tool. Rerun with --help for details.");
- return null;
- }
- else
- {
- Console.WriteLine($"Detected project type {projectDescription.Identifier}. ");
- }
-
// Case of a blazorwasm hosted application. We need to create two applications:
// - the hosted web API
// - the SPA.
- if (projectSettings.ApplicationParameters.IsBlazorWasm && projectSettings.ApplicationParameters.IsWebApi)
+ if (projectSettings.ApplicationParameters.IsBlazorWasm.HasValue && projectSettings.ApplicationParameters.IsBlazorWasm.Value
+ && projectSettings.ApplicationParameters.IsWebApi.HasValue && projectSettings.ApplicationParameters.IsWebApi.Value)
{
// Processes the hosted web API
ProvisioningToolOptions provisioningToolOptionsBlazorServer = ProvisioningToolOptions.Clone();
provisioningToolOptionsBlazorServer.ProjectPath = Path.Combine(ProvisioningToolOptions.ProjectPath, "Server");
+ provisioningToolOptionsBlazorServer.AppDisplayName = string.Concat(provisioningToolOptionsBlazorServer.AppDisplayName ?? projectSettings.ApplicationParameters.ApplicationDisplayName, "-Server");
+ provisioningToolOptionsBlazorServer.ProjectType = string.Empty;
provisioningToolOptionsBlazorServer.ClientId = ProvisioningToolOptions.WebApiClientId;
provisioningToolOptionsBlazorServer.WebApiClientId = null;
AppProvisioningTool appProvisioningToolBlazorServer = new AppProvisioningTool(CommandName, provisioningToolOptionsBlazorServer);
@@ -129,6 +122,8 @@ public AppProvisioningTool(string commandName, ProvisioningToolOptions provision
/// Processes the Blazorwasm client
ProvisioningToolOptions provisioningToolOptionsBlazorClient = ProvisioningToolOptions.Clone();
provisioningToolOptionsBlazorClient.ProjectPath = Path.Combine(ProvisioningToolOptions.ProjectPath, "Client");
+ provisioningToolOptionsBlazorClient.AppDisplayName = string.Concat(provisioningToolOptionsBlazorClient.AppDisplayName ?? projectSettings.ApplicationParameters.ApplicationDisplayName, "-Client");
+ provisioningToolOptionsBlazorClient.ProjectType = string.Empty;
provisioningToolOptionsBlazorClient.WebApiClientId = applicationParametersServer?.ClientId;
provisioningToolOptionsBlazorClient.AppIdUri = applicationParametersServer?.AppIdUri;
provisioningToolOptionsBlazorClient.CalledApiScopes = $"{applicationParametersServer?.AppIdUri}/access_as_user";
@@ -136,17 +131,45 @@ public AppProvisioningTool(string commandName, ProvisioningToolOptions provision
return await appProvisioningToolBlazorClient.Run();
}
+ switch (CommandName)
+ {
+ case Commands.UPDATE_PROJECT_COMMAND:
+ applicationParameters = await ReadMicrosoftIdentityApplication(tokenCredential, projectSettings.ApplicationParameters);
+ await UpdateProject(tokenCredential, applicationParameters);
+ return applicationParameters;
+
+ case Commands.UPDATE_APP_REGISTRATION_COMMAND:
+ applicationParameters = await ReadMicrosoftIdentityApplication(tokenCredential, projectSettings.ApplicationParameters);
+ await UpdateApplication(tokenCredential, applicationParameters);
+ return applicationParameters;
+
+ case Commands.UNREGISTER_APPLICATION_COMMAND:
+ await UnregisterApplication(tokenCredential, projectSettings.ApplicationParameters);
+ return null;
+
+ case Commands.CREATE_APP_REGISTRATION_COMMAND:
+ return await CreateAppRegistration(tokenCredential, projectSettings.ApplicationParameters);
+
+ case Commands.ADD_CLIENT_SECRET:
+ applicationParameters = await ReadMicrosoftIdentityApplication(tokenCredential, projectSettings.ApplicationParameters);
+ await AddClientSecret(tokenCredential, applicationParameters);
+ return applicationParameters;
+ }
+
// Case where the developer wants to have a B2C application, but the created application is an AAD one. The
// tool needs to convert it
if (!projectSettings.ApplicationParameters.IsB2C && !string.IsNullOrEmpty(ProvisioningToolOptions.SusiPolicyId))
{
- projectSettings = ConvertAadApplicationToB2CApplication(projectDescription, projectSettings);
+ if (projectDescription != null)
+ {
+ projectSettings = ConvertAadApplicationToB2CApplication(projectDescription, projectSettings);
+ }
}
// Case where there is no code for the authentication
if (!projectSettings.ApplicationParameters.HasAuthentication)
{
- Console.WriteLine($"Authentication is not enabled yet in this project. An app registration will " +
+ ConsoleLogger.LogMessage($"Authentication is not enabled yet in this project. An app registration will " +
$"be created, but the tool does not add the code yet (work in progress). ");
}
@@ -186,6 +209,25 @@ await WriteApplicationRegistration(
return effectiveApplicationParameters;
}
+ private async Task CreateAppRegistration(TokenCredential tokenCredential, ApplicationParameters? applicationParameters)
+ {
+ ApplicationParameters? resultAppParameters = null;
+ if (applicationParameters != null)
+ {
+ resultAppParameters = await MicrosoftIdentityPlatformApplicationManager.CreateNewAppAsync(tokenCredential, applicationParameters, ConsoleLogger, CommandName);
+ if (resultAppParameters != null && !string.IsNullOrEmpty(resultAppParameters.ClientId))
+ {
+ ConsoleLogger.LogMessage($"Created app {resultAppParameters.ApplicationDisplayName} - {resultAppParameters.ClientId}.");
+ }
+ else
+ {
+ string failMessage = "Failed to create Azure AD/AD B2C app";
+ ConsoleLogger.LogMessage(failMessage, LogMessageType.Error);
+ }
+ }
+ return resultAppParameters;
+ }
+
// add 'AzureAd', 'MicrosoftGraph' or 'DownstreamAPI' sections as appropriate. Fill them default values if empty.
// Default values can be found https://github.com/dotnet/aspnetcore/tree/main/src/ProjectTemplates/Web.ProjectTemplates/content
private void ModifyAppSettings(ApplicationParameters applicationParameters)
@@ -344,7 +386,7 @@ private ProjectAuthenticationSettings ConvertAadApplicationToB2CApplication(Proj
if (projectSettings.ApplicationParameters.CallsMicrosoftGraph)
{
- Console.WriteLine("You'll need to remove the calls to Microsoft Graph as it's not supported by B2C apps.");
+ ConsoleLogger.LogMessage("You'll need to remove the calls to Microsoft Graph as it's not supported by B2C apps.", LogMessageType.Error);
}
// reevaulate the project settings
@@ -357,10 +399,10 @@ private ProjectAuthenticationSettings ConvertAadApplicationToB2CApplication(Proj
private void WriteSummary(Summary summary)
{
- Console.WriteLine("Summary");
+ ConsoleLogger.LogMessage("Summary");
foreach (Change change in summary.changes)
{
- Console.WriteLine($"{change.Description}");
+ ConsoleLogger.LogMessage($"{change.Description}");
}
}
@@ -372,7 +414,7 @@ private async Task WriteApplicationRegistration(Summary summary, ApplicationPara
private void WriteProjectConfiguration(Summary summary, ProjectAuthenticationSettings projectSettings, ApplicationParameters reconcialedApplicationParameters)
{
- CodeWriter.WriteConfiguration(summary, projectSettings.Replacements, reconcialedApplicationParameters, ProvisioningToolOptions.Json);
+ CodeWriter.WriteConfiguration(summary, projectSettings.Replacements, reconcialedApplicationParameters, ConsoleLogger);
}
private bool Reconciliate(ApplicationParameters applicationParameters, ApplicationParameters effectiveApplicationParameters)
@@ -408,7 +450,7 @@ private bool Reconciliate(ApplicationParameters applicationParameters, Applicati
currentApplicationParameters = await MicrosoftIdentityPlatformApplicationManager.ReadApplication(tokenCredential, applicationParameters);
if (currentApplicationParameters == null)
{
- Console.Write($"Couldn't find app {applicationParameters.EffectiveClientId} in tenant {applicationParameters.EffectiveTenantId}. ");
+ ConsoleLogger.LogMessage($"Couldn't find app {applicationParameters.EffectiveClientId} in tenant {applicationParameters.EffectiveTenantId}. ", LogMessageType.Error);
}
}
return currentApplicationParameters;
@@ -424,14 +466,21 @@ private bool Reconciliate(ApplicationParameters applicationParameters, Applicati
currentApplicationParameters = await MicrosoftIdentityPlatformApplicationManager.ReadApplication(tokenCredential, applicationParameters);
if (currentApplicationParameters == null)
{
- Console.Write($"Couldn't find app {applicationParameters.EffectiveClientId} in tenant {applicationParameters.EffectiveTenantId}. ");
+ ConsoleLogger.LogMessage($"Couldn't find app {applicationParameters.EffectiveClientId} in tenant {applicationParameters.EffectiveTenantId}. ", LogMessageType.Error);
}
}
if (currentApplicationParameters == null && !ProvisioningToolOptions.Unregister)
{
- currentApplicationParameters = await MicrosoftIdentityPlatformApplicationManager.CreateNewApp(tokenCredential, applicationParameters, ProvisioningToolOptions.Json);
- Console.Write($"Created app {currentApplicationParameters.ClientId}. ");
+ currentApplicationParameters = await MicrosoftIdentityPlatformApplicationManager.CreateNewAppAsync(tokenCredential, applicationParameters, ConsoleLogger, CommandName);
+ if (currentApplicationParameters != null)
+ {
+ ConsoleLogger.LogMessage($"Created app {currentApplicationParameters.ApplicationDisplayName} - {currentApplicationParameters.ClientId}. ");
+ }
+ else
+ {
+ ConsoleLogger.LogMessage("Failed to create Azure AD/AD B2C app registration", LogMessageType.Error);
+ }
}
return currentApplicationParameters;
}
@@ -449,10 +498,31 @@ private ProjectAuthenticationSettings InferApplicationParameters(
}
// Override with the tools options
- projectSettings.ApplicationParameters.ApplicationDisplayName ??= Path.GetFileName(provisioningToolOptions.ProjectPath);
+ projectSettings.ApplicationParameters.ApplicationDisplayName ??= !string.IsNullOrEmpty(provisioningToolOptions.AppDisplayName) ? provisioningToolOptions.AppDisplayName : Path.GetFileName(provisioningToolOptions.ProjectPath);
projectSettings.ApplicationParameters.ClientId = !string.IsNullOrEmpty(provisioningToolOptions.ClientId) ? provisioningToolOptions.ClientId : projectSettings.ApplicationParameters.ClientId;
projectSettings.ApplicationParameters.TenantId = !string.IsNullOrEmpty(provisioningToolOptions.TenantId) ? provisioningToolOptions.TenantId : projectSettings.ApplicationParameters.TenantId;
projectSettings.ApplicationParameters.CalledApiScopes = !string.IsNullOrEmpty(provisioningToolOptions.CalledApiScopes) ? provisioningToolOptions.CalledApiScopes : projectSettings.ApplicationParameters.CalledApiScopes;
+
+ //there can mutliple project types
+ if (!string.IsNullOrEmpty(provisioningToolOptions.ProjectType))
+ {
+ if (provisioningToolOptions.ProjectType.Equals("webapp", StringComparison.OrdinalIgnoreCase))
+ {
+ projectSettings.ApplicationParameters.IsWebApp = projectSettings.ApplicationParameters.IsWebApp ?? true;
+ }
+ if (provisioningToolOptions.ProjectType.Equals("webapi", StringComparison.OrdinalIgnoreCase))
+ {
+ projectSettings.ApplicationParameters.IsWebApi = projectSettings.ApplicationParameters.IsWebApi ?? true;
+ }
+ if (provisioningToolOptions.ProjectType.Equals("blazorwasm", StringComparison.OrdinalIgnoreCase))
+ {
+ projectSettings.ApplicationParameters.IsBlazorWasm = projectSettings.ApplicationParameters.IsBlazorWasm ?? true;
+ }
+ if (provisioningToolOptions.ProjectType.Equals("blazorwasm-hosted", StringComparison.OrdinalIgnoreCase))
+ {
+ projectSettings.ApplicationParameters.IsBlazorWasm = projectSettings.ApplicationParameters.IsBlazorWasm ?? true;
+ }
+ }
if (!string.IsNullOrEmpty(provisioningToolOptions.AppIdUri))
{
projectSettings.ApplicationParameters.AppIdUri = provisioningToolOptions.AppIdUri;
@@ -470,7 +540,24 @@ private TokenCredential GetTokenCredential(ProvisioningToolOptions provisioningT
private async Task UnregisterApplication(TokenCredential tokenCredential, ApplicationParameters applicationParameters)
{
- await MicrosoftIdentityPlatformApplicationManager.Unregister(tokenCredential, applicationParameters);
+ bool unregisterSuccess = await MicrosoftIdentityPlatformApplicationManager.UnregisterAsync(tokenCredential, applicationParameters);
+ JsonResponse jsonResponse = new JsonResponse(CommandName);
+ if (unregisterSuccess)
+ {
+ string outputMessage = $"Unregistered the Azure AD w/ client id = {applicationParameters.ClientId}\n";
+ jsonResponse.State = State.Success;
+ jsonResponse.Content = outputMessage;
+ ConsoleLogger.LogMessage(outputMessage);
+ ConsoleLogger.LogJsonMessage(jsonResponse);
+ }
+ else
+ {
+ string outputMessage = $"Unable to unregister the Azure AD w/ client id = {applicationParameters.ClientId}\n";
+ jsonResponse.State = State.Fail;
+ jsonResponse.Content = outputMessage;
+ ConsoleLogger.LogMessage(outputMessage);
+ ConsoleLogger.LogJsonMessage(jsonResponse);
+ }
}
private async Task UpdateApplication(TokenCredential tokenCredential, ApplicationParameters? applicationParameters)
@@ -497,28 +584,28 @@ private async Task UpdateApplication(TokenCredential tokenCredential, Applicatio
jsonResponse.State = State.Fail;
}
- Console.WriteLine(ProvisioningToolOptions.Json ? jsonResponse.ToJsonString() : jsonResponse.Content);
+ ConsoleLogger.LogMessage(jsonResponse.Content as string);
+ ConsoleLogger.LogJsonMessage(jsonResponse);
}
private async Task AddClientSecret(TokenCredential tokenCredential, ApplicationParameters? applicationParameters)
{
JsonResponse jsonResponse = new JsonResponse(CommandName);
- string outputString;
if (applicationParameters != null && !string.IsNullOrEmpty(applicationParameters.GraphEntityId))
{
var graphServiceClient = MicrosoftIdentityPlatformApplicationManager.GetGraphServiceClient(tokenCredential);
- string? password = await MicrosoftIdentityPlatformApplicationManager.AddPasswordCredentials(
+ string? password = await MicrosoftIdentityPlatformApplicationManager.AddPasswordCredentialsAsync(
graphServiceClient,
applicationParameters.GraphEntityId,
applicationParameters,
- ProvisioningToolOptions.Json);
+ ConsoleLogger);
//if user wants to update user secrets
if (ProvisioningToolOptions.UpdateUserSecrets)
{
- CodeWriter.AddUserSecrets(applicationParameters.IsB2C, ProvisioningToolOptions.ProjectPath, password, ProvisioningToolOptions.Json);
+ CodeWriter.AddUserSecrets(applicationParameters.IsB2C, ProvisioningToolOptions.ProjectPath, password, ConsoleLogger);
}
if (!string.IsNullOrEmpty(password))
@@ -526,7 +613,8 @@ private async Task AddClientSecret(TokenCredential tokenCredential, ApplicationP
jsonResponse.State = State.Success;
jsonResponse.Content = new KeyValuePair("ClientSecret", password);
string secretOutput = $"Client secret - {password}.";
- outputString = ProvisioningToolOptions.Json ? jsonResponse.ToJsonString() : secretOutput;
+ ConsoleLogger.LogMessage(secretOutput);
+ ConsoleLogger.LogJsonMessage(jsonResponse);
}
else
@@ -534,7 +622,8 @@ private async Task AddClientSecret(TokenCredential tokenCredential, ApplicationP
string failedOutput = $"Failed to add client secret for Azure AD app : {applicationParameters.ApplicationDisplayName}({applicationParameters.ClientId})";
jsonResponse.State = State.Fail;
jsonResponse.Content = failedOutput;
- outputString = ProvisioningToolOptions.Json ? jsonResponse.ToJsonString() : failedOutput;
+ ConsoleLogger.LogMessage(failedOutput);
+ ConsoleLogger.LogJsonMessage(jsonResponse);
}
}
else
@@ -542,9 +631,9 @@ private async Task AddClientSecret(TokenCredential tokenCredential, ApplicationP
string failedOutput = $"Failed to add client secret.";
jsonResponse.State = State.Fail;
jsonResponse.Content = failedOutput;
- outputString = ProvisioningToolOptions.Json ? jsonResponse.ToJsonString() : failedOutput;
+ ConsoleLogger.LogMessage(failedOutput);
+ ConsoleLogger.LogJsonMessage(jsonResponse);
}
- Console.WriteLine(outputString);
}
private async Task UpdateProject(TokenCredential tokenCredential, ApplicationParameters? applicationParameters)
@@ -561,17 +650,17 @@ private async Task UpdateProject(TokenCredential tokenCredential, ApplicationPar
//need ClientId and Microsoft.Graph.Application.Id(GraphEntityId)
if (graphServiceClient != null && !string.IsNullOrEmpty(applicationParameters.ClientId) && !string.IsNullOrEmpty(applicationParameters.GraphEntityId))
{
- await MicrosoftIdentityPlatformApplicationManager.AddPasswordCredentials(
+ await MicrosoftIdentityPlatformApplicationManager.AddPasswordCredentialsAsync(
graphServiceClient,
applicationParameters.GraphEntityId,
applicationParameters,
- ProvisioningToolOptions.Json);
+ ConsoleLogger);
string? password = applicationParameters.PasswordCredentials.LastOrDefault();
//if user wants to update user secrets
if (!string.IsNullOrEmpty(password) && ProvisioningToolOptions.UpdateUserSecrets)
{
- CodeWriter.AddUserSecrets(applicationParameters.IsB2C, ProvisioningToolOptions.ProjectPath, password, ProvisioningToolOptions.Json);
+ CodeWriter.AddUserSecrets(applicationParameters.IsB2C, ProvisioningToolOptions.ProjectPath, password, ConsoleLogger);
}
}
}
diff --git a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/Commands.cs b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/Commands.cs
index 915e15236..57c8f971f 100644
--- a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/Commands.cs
+++ b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/Commands.cs
@@ -5,11 +5,11 @@ public class Commands
public const string LIST_AAD_APPS_COMMAND = "--list-aad-apps";
public const string LIST_SERVICE_PRINCIPALS_COMMAND = "--list-service-principals";
public const string LIST_TENANTS_COMMAND = "--list-tenants";
- public const string ADD_CLIENT_SECRET = "--add-client-secret";
public const string REGISTER_APPLICATIION_COMMAND = "--register-app";
- public const string UPDATE_APPLICATION_COMMAND = "--update-app-registration";
- public const string UPDATE_PROJECT_COMMAND = "--update-project";
public const string UNREGISTER_APPLICATION_COMMAND = "--unregister-app";
- public const string VALIDATE_APP_PARAMS_COMMAND = "--validate-app-params";
+ public const string ADD_CLIENT_SECRET = "--create-client-secret";
+ public const string CREATE_APP_REGISTRATION_COMMAND = "--create-app-registration";
+ public const string UPDATE_APP_REGISTRATION_COMMAND = "--update-app-registration";
+ public const string UPDATE_PROJECT_COMMAND = "--update-project";
}
}
diff --git a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/ConsoleLogger.cs b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/ConsoleLogger.cs
new file mode 100644
index 000000000..31ada6a0c
--- /dev/null
+++ b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/ConsoleLogger.cs
@@ -0,0 +1,61 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Microsoft.DotNet.MSIdentity.Tool
+{
+ internal class ConsoleLogger : IConsoleLogger
+ {
+ private bool _jsonOutput;
+
+ public ConsoleLogger(bool jsonOutput = false)
+ {
+ _jsonOutput = jsonOutput;
+ Console.OutputEncoding = Encoding.UTF8;
+ }
+
+ public void LogMessage(string? message, LogMessageType level, bool removeNewLine = false)
+ {
+ //if json output is enabled, don't write to console at all.
+ if (!_jsonOutput)
+ {
+ switch (level)
+ {
+ case LogMessageType.Error:
+ if (removeNewLine)
+ {
+ Console.Error.Write(message);
+ }
+ else
+ {
+ Console.Error.WriteLine(message);
+ }
+ break;
+ case LogMessageType.Information:
+ if (removeNewLine)
+ {
+ Console.Write(message);
+ }
+ else
+ {
+ Console.WriteLine(message);
+ }
+ break;
+ }
+ }
+ }
+
+ public void LogJsonMessage(JsonResponse jsonMessage)
+ {
+ if (_jsonOutput)
+ {
+ Console.WriteLine(jsonMessage.ToJsonString());
+ }
+ }
+
+ public void LogMessage(string? message, bool removeNewLine = false)
+ {
+ LogMessage(message, LogMessageType.Information, removeNewLine);
+ }
+ }
+}
diff --git a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/IConsoleLogger.cs b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/IConsoleLogger.cs
new file mode 100644
index 000000000..2aebe93b9
--- /dev/null
+++ b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/IConsoleLogger.cs
@@ -0,0 +1,19 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+
+namespace Microsoft.DotNet.MSIdentity.Tool
+{
+ public interface IConsoleLogger
+ {
+ void LogMessage(string? message, LogMessageType level, bool removeNewLine = false);
+ void LogMessage(string? message, bool removeNewLine = false);
+ void LogJsonMessage(JsonResponse jsonMessage);
+ }
+
+ public enum LogMessageType
+ {
+ Error,
+ Information
+ }
+}
diff --git a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/JsonResponse.cs b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/JsonResponse.cs
index 023d0bfdb..9dd346ed0 100644
--- a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/JsonResponse.cs
+++ b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/JsonResponse.cs
@@ -3,7 +3,7 @@
namespace Microsoft.DotNet.MSIdentity.Tool
{
- internal class JsonResponse
+ public class JsonResponse
{
public string Command { get; }
public string? State { get; set; }
diff --git a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/MsAADTool.cs b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/MsAADTool.cs
index 412c1cd79..cdeb6a0cd 100644
--- a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/MsAADTool.cs
+++ b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/MsAADTool.cs
@@ -14,6 +14,7 @@ namespace Microsoft.DotNet.MSIdentity.Tool
{
internal class MsAADTool : IMsAADTool
{
+ internal IConsoleLogger ConsoleLogger { get; }
private ProvisioningToolOptions ProvisioningToolOptions { get; set; }
private string CommandName { get; }
public IGraphServiceClient GraphServiceClient { get; set; }
@@ -27,6 +28,7 @@ public MsAADTool(string commandName, ProvisioningToolOptions provisioningToolOpt
TokenCredential = new MsalTokenCredential(ProvisioningToolOptions.TenantId, ProvisioningToolOptions.Username);
GraphServiceClient = new GraphServiceClient(new TokenCredentialAuthenticationProvider(TokenCredential));
AzureManagementAPI = new AzureManagementAuthenticationProvider(TokenCredential);
+ ConsoleLogger = new ConsoleLogger(ProvisioningToolOptions.Json);
}
public async Task Run()
diff --git a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/ProvisioningToolOptions.cs b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/ProvisioningToolOptions.cs
index 624efe1a7..91ccaf72f 100644
--- a/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/ProvisioningToolOptions.cs
+++ b/src/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity/Tool/ProvisioningToolOptions.cs
@@ -20,6 +20,11 @@ public class ProvisioningToolOptions : IDeveloperCredentialsOptions
///
public string? AppSettingsFilePath { get; set; }
+ ///
+ /// Display name for Azure AD/AD B2C app registration
+ ///
+ public string? AppDisplayName { get; set; }
+
///
/// Web redirect URIs.
///
@@ -168,7 +173,8 @@ public ProvisioningToolOptions Clone()
AppSettingsFilePath = AppSettingsFilePath,
WebApiClientId = WebApiClientId,
AppIdUri = AppIdUri,
- Json = Json
+ Json = Json,
+ AppDisplayName = AppDisplayName
};
}
}
diff --git a/test/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity.Tests/ProjectDescriptionReaderTests.cs b/test/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity.Tests/ProjectDescriptionReaderTests.cs
index 50bdba71e..6dd6d28ea 100644
--- a/test/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity.Tests/ProjectDescriptionReaderTests.cs
+++ b/test/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity.Tests/ProjectDescriptionReaderTests.cs
@@ -179,7 +179,10 @@ public void TestProjectDescriptionReader_TemplatesWithNoAuth(string folderPath,
private void AssertAuthSettings(ProjectAuthenticationSettings authenticationSettings, bool isB2C = false)
{
- Assert.True(authenticationSettings.ApplicationParameters.IsWebApi || authenticationSettings.ApplicationParameters.IsWebApp || authenticationSettings.ApplicationParameters.IsBlazorWasm);
+ bool IsWebApi = authenticationSettings.ApplicationParameters.IsWebApi.HasValue && authenticationSettings.ApplicationParameters.IsWebApi.Value;
+ bool IsWebApp = authenticationSettings.ApplicationParameters.IsWebApp.HasValue && authenticationSettings.ApplicationParameters.IsWebApp.Value;
+ bool IsBlazorWasm = authenticationSettings.ApplicationParameters.IsBlazorWasm.HasValue && authenticationSettings.ApplicationParameters.IsBlazorWasm.Value;
+ Assert.True(IsWebApi || IsWebApp || IsBlazorWasm);
if (isB2C)
{
diff --git a/test/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity.UnitTests.Tests/MicrosoftIdentityPlatformApplicationManagerTests.cs b/test/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity.UnitTests.Tests/MicrosoftIdentityPlatformApplicationManagerTests.cs
new file mode 100644
index 000000000..e1985ec0a
--- /dev/null
+++ b/test/MSIdentityScaffolding/Microsoft.DotNet.MSIdentity.UnitTests.Tests/MicrosoftIdentityPlatformApplicationManagerTests.cs
@@ -0,0 +1,54 @@
+using Microsoft.DotNet.MSIdentity.MicrosoftIdentityPlatformApplication;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Xunit;
+
+namespace Microsoft.DotNet.MSIdentity.UnitTests.Tests
+{
+ public class MicrosoftIdentityPlatformApplicationManagerTests
+ {
+ [Theory]
+ [MemberData(nameof(UriList))]
+ public void ValidateUrisTests(List urisToValidate, List validUris)
+ {
+ var validatedUris = MicrosoftIdentityPlatformApplicationManager.ValidateUris(urisToValidate);
+ var areEquivalent = (validUris.Count == validatedUris.Count) && !validatedUris.Except(validUris).Any();
+ Assert.True(areEquivalent);
+ }
+
+ public static IEnumerable