Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dotnet-msidentity Preview 1 #1548

Merged
merged 5 commits into from
Apr 12, 2021
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions eng/Versions.MsIdentity.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,6 @@
<UsingToolXliff>false</UsingToolXliff>
<UsingToolNetFrameworkReferenceAssemblies>true</UsingToolNetFrameworkReferenceAssemblies>
</PropertyGroup>
<!-- Production Dependencies -->
<PropertyGroup>
<MicrosoftBuildFrameworkPackageVersion>$(MicrosoftBuildPackageVersion)</MicrosoftBuildFrameworkPackageVersion>
<MicrosoftBuildRuntimePackageVersion>$(MicrosoftBuildPackageVersion)</MicrosoftBuildRuntimePackageVersion>
<MicrosoftBuildUtilitiesCorePackageVersion>$(MicrosoftBuildPackageVersion)</MicrosoftBuildUtilitiesCorePackageVersion>
<!-- Ref packages -->
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>1.0.0</VersionPrefix>
<PreReleaseVersionLabel>preview</PreReleaseVersionLabel>
Expand Down
2 changes: 1 addition & 1 deletion eng/Versions.props
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
<MicrosoftExtensionsDependencyInjectionPackageVersion>6.0.0-preview.3.21201.4</MicrosoftExtensionsDependencyInjectionPackageVersion>
<!-- Microsoft.Extensions.FileProviders.Physical -->
<MicrosoftExtensionsFileProvidersPhysicalPackageVersion>6.0.0-preview.3.21201.4</MicrosoftExtensionsFileProvidersPhysicalPackageVersion>
<NewtonsoftJsonPackageVersion>11.0.2</NewtonsoftJsonPackageVersion>
<NewtonsoftJsonPackageVersion>13.0.1</NewtonsoftJsonPackageVersion>
deepchoudhery marked this conversation as resolved.
Show resolved Hide resolved
<VisualStudio_NewtonsoftJsonPackageVersion>9.0.1</VisualStudio_NewtonsoftJsonPackageVersion>
<SystemCollectionsImmutablePackageVersion>5.0.0</SystemCollectionsImmutablePackageVersion>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using System;
Expand All @@ -16,6 +16,11 @@ public class ApplicationParameters
/// </summary>
public string? ApplicationDisplayName { get; set; }

/// <summary>
/// Application project path
/// <summary>
public string? ProjectPath { get; set; }

/// <summary>
/// Tenant in which the application is created.
/// </summary>
Expand Down Expand Up @@ -179,6 +184,11 @@ public string? Domain1
/// </summary>
public string? MsalAuthenticationOptions { get; set; }

/// <summary>
/// Graph.Application and Graph.ServicePrincipal object ids.
/// </summary>
public string? GraphEntityId { get; set; }

/// <summary>
/// Sets a bool property (from its name).
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace Microsoft.DotNet.MsIdentity.AuthenticationParameters
{
public class AzureAdProperties
{
public string? Domain { get; set; }
public string? TenantId { get; set; }
public string? ClientId { get; set; }
public string? ClientSecret { get; set; }
public string? CallbackPath { get; set; }
public string? Instance { get; set; }
}

//getting default properties from https://github.com/dotnet/aspnetcore/blob/6bc4b79f4ee7af00edcbb435e5ee4c1de349a110/src/ProjectTemplates/Web.ProjectTemplates/content/StarterWeb-CSharp/appsettings.json
public static class AzureAdDefaultProperties
{
public const string Domain = "qualified.domain.name";
public const string TenantId = "22222222-2222-2222-2222-222222222222";
public const string ClientId = "11111111-1111-1111-11111111111111111";
public const string Instance = "https://login.microsoftonline.com/";
public const string CallbackPath = "/signin-oidc";
}
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Microsoft.DotNet.MsIdentity.AuthenticationParameters;
using Microsoft.DotNet.MsIdentity.Project;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Microsoft.DotNet.MsIdentity.AuthenticationParameters;
using Microsoft.DotNet.MsIdentity.Project;
using Microsoft.Extensions.Internal;

namespace Microsoft.DotNet.MsIdentity.CodeReaderWriter
{
public class CodeWriter
public static class CodeWriter
{
internal void WriteConfiguration(Summary summary, IEnumerable<Replacement> replacements, ApplicationParameters reconcialedApplicationParameters)
internal static void WriteConfiguration(Summary summary, IEnumerable<Replacement> replacements, ApplicationParameters reconcialedApplicationParameters)
{
foreach (var replacementsInFile in replacements.GroupBy(r => r.FilePath))
{
Expand Down Expand Up @@ -49,36 +49,86 @@ internal void WriteConfiguration(Summary summary, IEnumerable<Replacement> repla
}
}

private string? ComputeReplacement(string replaceBy, ApplicationParameters reconciledApplicationParameters)
public static void AddUserSecrets(bool isB2C, string projectPath, string value)
{
//init regardless. If it's already initiated, dotnet-user-secrets confirms it.
InitUserSecrets(projectPath);
string section = isB2C ? "AzureADB2C" : "AzureAD";
string key = $"{section}:ClientSecret";
SetUserSecerets(projectPath, key, value);
}
private static void InitUserSecrets(string projectPath)
{
var errors = new List<string>();
var output = new List<string>();

IList<string> arguments = new List<string>();

//if project path is present, use it for dotnet user-secrets
if (!string.IsNullOrEmpty(projectPath))
{
arguments.Add("-p");
arguments.Add(projectPath);
}

arguments.Add("init");
var result = Command.CreateDotNet(
"user-secrets",
arguments.ToArray())
.OnErrorLine(e => errors.Add(e))
.OnOutputLine(o => output.Add(o))
.Execute();

if (result.ExitCode != 0)
{
throw new Exception("Error while running dotnet-user-secrets init");
}
}

private static void SetUserSecerets(string projectPath, string key, string value)
{
var errors = new List<string>();
var output = new List<string>();

IList<string> arguments = new List<string>();

//if project path is present, use it for dotnet user-secrets
if (!string.IsNullOrEmpty(projectPath))
{
arguments.Add("-p");
arguments.Add(projectPath);
}

arguments.Add("set");
arguments.Add(key);
arguments.Add(value);
var result = Command.CreateDotNet(
"user-secrets",
arguments)
.OnErrorLine(e => errors.Add(e))
.OnOutputLine(o => output.Add(o))
.Execute();

if (result.ExitCode != 0)
{
throw new Exception($"Error while running dotnet-user-secrets set {key} {value}");
}
else
{
Console.WriteLine($"\nAdded {key} to user secrets.\n");
}
}

private static string? ComputeReplacement(string replaceBy, ApplicationParameters reconciledApplicationParameters)
{
string? replacement = replaceBy;
switch(replaceBy)
{
case "Application.ClientSecret":
string? password = reconciledApplicationParameters.PasswordCredentials.LastOrDefault();
if (!string.IsNullOrEmpty(reconciledApplicationParameters.SecretsId))
if (!string.IsNullOrEmpty(reconciledApplicationParameters.SecretsId) && !string.IsNullOrEmpty(password))
{
// TODO: adapt for Linux: https://docs.microsoft.com/en-us/aspnet/core/security/app-secrets?view=aspnetcore-5.0&tabs=windows#how-the-secret-manager-tool-works
string? envVariable = Environment.GetEnvironmentVariable("UserProfile");
if (!string.IsNullOrEmpty(envVariable))
{
string path = Path.Combine(
envVariable,
@"AppData\Roaming\Microsoft\UserSecrets\",
reconciledApplicationParameters.SecretsId,
"secrets.json")!;
if (!File.Exists(path))
{
Directory.CreateDirectory(Path.GetDirectoryName(path)!);
string section = reconciledApplicationParameters.IsB2C ? "AzureADB2C" : "AzureAD";
File.WriteAllText(path, $"{{\n \"{section}:ClientSecret\": \"{password}\"\n}}");
replacement = "See user secrets";
}
else
{
replacement = password;
}
}
AddUserSecrets(reconciledApplicationParameters.IsB2C, reconciledApplicationParameters.ProjectPath ?? string.Empty, password);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>netcoreapp3.1;net5.0</TargetFrameworks>
Expand Down Expand Up @@ -32,8 +32,14 @@
<PackageReference Include="Microsoft.Graph" Version="$(MicrosoftGraphVersion)" />
<PackageReference Include="Microsoft.Identity.Client.Extensions.Msal" Version="$(MicrosoftIdentityClientExtensionsMsalVersion)" />
<PackageReference Include="System.Text.Json" Version="$(SystemTextJsonVersion)" />
<PackageReference Include="Newtonsoft.Json" Version="$(NewtonsoftJsonPackageVersion)" />
</ItemGroup>

<ItemGroup>
<Compile Include="..\..\Scaffolding\Shared\Cli.Utils\*.cs">
<Link>Shared\%(RecursiveDir)%(FileName).cs</Link>
</Compile>
</ItemGroup>
<ItemGroup>
<Folder Include="Resources\" />
</ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

using Azure.Core;
using Microsoft.DotNet.MsIdentity.AuthenticationParameters;
using Microsoft.Graph;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using Azure.Core;
using Microsoft.DotNet.MsIdentity.AuthenticationParameters;
using Microsoft.Graph;

namespace Microsoft.DotNet.MsIdentity.MicrosoftIdentityPlatformApplication
{
Expand Down Expand Up @@ -123,7 +122,7 @@ await AddApiPermissionFromBlazorwasmHostedSpaToServerApi(
{
await AddPasswordCredentials(
graphServiceClient,
createdApplication,
createdApplication.Id,
effectiveApplicationParameters);
}

Expand Down Expand Up @@ -193,7 +192,7 @@ await graphServiceClient.Applications[existingApplication.Id]
{
await AddPasswordCredentials(
graphServiceClient,
existingApplication,
existingApplication.Id,
reconcialedApplicationParameters).ConfigureAwait(false);
}
}
Expand Down Expand Up @@ -251,18 +250,21 @@ await graphServiceClient.Oauth2PermissionGrants
/// <param name="createdApplication"></param>
/// <param name="effectiveApplicationParameters"></param>
/// <returns></returns>
private static async Task AddPasswordCredentials(GraphServiceClient graphServiceClient, Application createdApplication, ApplicationParameters effectiveApplicationParameters)
internal static async Task AddPasswordCredentials(GraphServiceClient graphServiceClient, string applicatonId, ApplicationParameters effectiveApplicationParameters)
{
var passwordCredential = new PasswordCredential
{
DisplayName = "Password created by the provisioning tool"
DisplayName = "Secret created by dotnet-msidentity tool"
};

PasswordCredential returnedPasswordCredential = await graphServiceClient.Applications[$"{createdApplication.Id}"]
.AddPassword(passwordCredential)
.Request()
.PostAsync();
effectiveApplicationParameters.PasswordCredentials.Add(returnedPasswordCredential.SecretText);
if (!string.IsNullOrEmpty(applicatonId) && graphServiceClient != null)
{
PasswordCredential returnedPasswordCredential = await graphServiceClient.Applications[$"{applicatonId}"]
.AddPassword(passwordCredential)
.Request()
.PostAsync();
effectiveApplicationParameters.PasswordCredentials.Add(returnedPasswordCredential.SecretText);
}
}

/// <summary>
Expand Down Expand Up @@ -539,7 +541,7 @@ await graphServiceClient.Applications[$"{readApplication.Id}"]
}
}

private GraphServiceClient GetGraphServiceClient(TokenCredential tokenCredential)
internal GraphServiceClient GetGraphServiceClient(TokenCredential tokenCredential)
{
if (_graphServiceClient == null)
{
Expand All @@ -551,10 +553,25 @@ private GraphServiceClient GetGraphServiceClient(TokenCredential tokenCredential
public async Task<ApplicationParameters?> ReadApplication(TokenCredential tokenCredential, ApplicationParameters applicationParameters)
{
var graphServiceClient = GetGraphServiceClient(tokenCredential);

// Get the tenant
Organization? tenant = await GetTenant(graphServiceClient);
var application = await GetApplication(tokenCredential, applicationParameters);
if (application != null)
{

ApplicationParameters effectiveApplicationParameters = GetEffectiveApplicationParameters(
tenant!,
application,
applicationParameters);

return effectiveApplicationParameters;
}
return null;
}

public async Task<Application?> GetApplication(TokenCredential tokenCredential, ApplicationParameters applicationParameters)
{
var graphServiceClient = GetGraphServiceClient(tokenCredential);
var apps = await graphServiceClient.Applications
.Request()
.Filter($"appId eq '{applicationParameters.ClientId}'")
Expand All @@ -566,14 +583,7 @@ private GraphServiceClient GetGraphServiceClient(TokenCredential tokenCredential
{
return null;
}

ApplicationParameters effectiveApplicationParameters = GetEffectiveApplicationParameters(
tenant!,
readApplication,
applicationParameters);

return effectiveApplicationParameters;

return readApplication;
}

private ApplicationParameters GetEffectiveApplicationParameters(
Expand Down Expand Up @@ -607,7 +617,8 @@ private ApplicationParameters GetEffectiveApplicationParameters(
TargetFramework = originalApplicationParameters.TargetFramework,
MsalAuthenticationOptions = originalApplicationParameters.MsalAuthenticationOptions,
CalledApiScopes = originalApplicationParameters.CalledApiScopes,
AppIdUri = originalApplicationParameters.AppIdUri
AppIdUri = originalApplicationParameters.AppIdUri,
GraphEntityId = application.Id
};

if (application.Api != null && application.IdentifierUris.Any())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ public class ProjectDescriptionReader
{
files = new string[0];
}

foreach (string filePath in files)
{
// If there are matches, one at least needs to match
Expand Down
Loading