From a8246e2a9906c647b7c444f735152a9f95534f97 Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Thu, 22 Mar 2018 22:01:59 -0700 Subject: [PATCH] [Fixes #327] Replace AAD template code with packages * Add Microsoft.AspNetCore.Authentication.AzureAD.UI package. * Add Microsoft.AspNetCore.Authentication.AzureADB2C.UI package. * Remove AccountController. * Remove Pages/Views related to authentication. --- build/dependencies.props | 2 + ...crosoft.DotNet.Web.ProjectTemplates.csproj | 2 + .../RazorPagesWeb-CSharp.csproj.in | 7 +- .../StarterWeb-CSharp.csproj.in | 7 +- .../WebApi-CSharp.csproj.in | 5 +- .../.template.config/template.json | 32 +- .../Controllers/AccountController.cs | 88 -- .../AzureAdAuthenticationBuilderExtensions.cs | 87 -- ...ureAdB2CAuthenticationBuilderExtensions.cs | 91 -- .../Extensions/AzureAdB2COptions.cs | 23 - .../Extensions/AzureAdOptions.cs | 17 - .../Pages/Account/AccessDenied.cshtml | 10 - .../Pages/Account/AccessDenied.cshtml.cs | 11 - .../Pages/Account/SignedOut.cshtml | 10 - .../Pages/Account/SignedOut.cshtml.cs | 23 - .../Pages/Shared/_LoginPartial.OrgAuth.cshtml | 41 +- .../Pages/_ViewImports.cshtml | 3 - .../content/RazorPagesWeb-CSharp/Startup.cs | 79 +- .../.template.config/template.json | 52 +- .../Controllers/AccountController.cs | 117 --- .../AzureAdAuthenticationBuilderExtensions.cs | 87 -- ...ureAdB2CAuthenticationBuilderExtensions.cs | 91 -- .../Extensions/AzureAdB2COptions.cs | 23 - .../Extensions/AzureAdOptions.cs | 17 - .../content/StarterWeb-CSharp/Startup.cs | 94 +- .../Views/Account/AccessDenied.cshtml | 8 - .../Views/Account/SignedOut.cshtml | 8 - .../Shared/_LoginPartial.Identity.cshtml | 25 + .../Views/Shared/_LoginPartial.OrgAuth.cshtml | 48 + .../Views/Shared/_LoginPartial.cshtml | 67 -- .../.template.config/template.json | 14 - .../AzureAdAuthenticationBuilderExtensions.cs | 43 - ...ureAdB2CAuthenticationBuilderExtensions.cs | 43 - .../Extensions/AzureAdB2COptions.cs | 10 - .../Extensions/AzureAdOptions.cs | 11 - .../content/WebApi-CSharp/Startup.cs | 24 +- test/Templates.Test/.gitattributes | 1 + test/Templates.Test/BaselineTest.cs | 73 ++ .../Helpers/TemplateTestBase.cs | 10 +- test/Templates.Test/Templates.Test.csproj | 4 + test/Templates.Test/template-baselines.json | 868 ++++++++++++++++++ 41 files changed, 1246 insertions(+), 1030 deletions(-) delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Controllers/AccountController.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdB2COptions.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdOptions.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/AccessDenied.cshtml delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/AccessDenied.cshtml.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/SignedOut.cshtml delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/SignedOut.cshtml.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Controllers/AccountController.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdB2COptions.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdOptions.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Account/AccessDenied.cshtml delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Account/SignedOut.cshtml create mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.Identity.cshtml create mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.OrgAuth.cshtml delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.cshtml delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdB2COptions.cs delete mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdOptions.cs create mode 100644 test/Templates.Test/.gitattributes create mode 100644 test/Templates.Test/BaselineTest.cs create mode 100644 test/Templates.Test/template-baselines.json diff --git a/build/dependencies.props b/build/dependencies.props index 2f1eaa4230..bb87397b28 100644 --- a/build/dependencies.props +++ b/build/dependencies.props @@ -5,6 +5,8 @@ 2.1.0-preview2-15749 2.1.0-preview2-30460 + 2.1.0-preview2-30460 + 2.1.0-preview2-30460 2.1.0-preview2-30460 2.1.0-preview2-30460 2.1.0-preview2-30460 diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj b/src/Microsoft.DotNet.Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj index 2829a3cdb0..d07e1fba9e 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/Microsoft.DotNet.Web.ProjectTemplates.csproj @@ -14,6 +14,8 @@ MicrosoftAspNetCoreAllPackageVersion=$(MicrosoftAspNetCoreAllPackageVersion); + MicrosoftAspNetCoreAuthenticationAzureADB2CUIPackageVersion=$(MicrosoftAspNetCoreAuthenticationAzureADB2CUIPackageVersion); + MicrosoftAspNetCoreAuthenticationAzureADUIPackageVersion=$(MicrosoftAspNetCoreAuthenticationAzureADUIPackageVersion); MicrosoftAspNetCoreAuthenticationCookiesPackageVersion=$(MicrosoftAspNetCoreAuthenticationCookiesPackageVersion); MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion=$(MicrosoftAspNetCoreAuthenticationJwtBearerPackageVersion); MicrosoftAspNetCoreAuthenticationOpenIdConnectPackageVersion=$(MicrosoftAspNetCoreAuthenticationOpenIdConnectPackageVersion); diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/RazorPagesWeb-CSharp.csproj.in b/src/Microsoft.DotNet.Web.ProjectTemplates/RazorPagesWeb-CSharp.csproj.in index d05703bbfd..badf7c619a 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/RazorPagesWeb-CSharp.csproj.in +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/RazorPagesWeb-CSharp.csproj.in @@ -14,6 +14,8 @@ + + @@ -21,8 +23,9 @@ - - + + + diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/StarterWeb-CSharp.csproj.in b/src/Microsoft.DotNet.Web.ProjectTemplates/StarterWeb-CSharp.csproj.in index 994653193b..1cb2e7c8a2 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/StarterWeb-CSharp.csproj.in +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/StarterWeb-CSharp.csproj.in @@ -16,14 +16,17 @@ + + - - + + + diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/WebApi-CSharp.csproj.in b/src/Microsoft.DotNet.Web.ProjectTemplates/WebApi-CSharp.csproj.in index b95724f554..9e843a089a 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/WebApi-CSharp.csproj.in +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/WebApi-CSharp.csproj.in @@ -14,10 +14,13 @@ + + - + + diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/template.json b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/template.json index 6387295ae7..b212bd08eb 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/template.json +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/.template.config/template.json @@ -37,18 +37,14 @@ ] }, { - "condition": "(!OrganizationalAuth && !IndividualB2CAuth)", - "rename": { - "Pages/Shared/_LoginPartial.Identity.cshtml": "Pages/Shared/_LoginPartial.cshtml" - }, + "condition": "(!OrganizationalAuth && !IndividualAuth)", "exclude": [ - "Controllers/**", - "Pages/Account/**", + "Pages/Shared/_LoginPartial.Identity.cshtml", "Pages/Shared/_LoginPartial.OrgAuth.cshtml" ] }, { - "condition": "(!IndividualLocalAuth)", + "condition": "(OrganizationalAuth || IndividualB2CAuth)", "rename": { "Pages/Shared/_LoginPartial.OrgAuth.cshtml": "Pages/Shared/_LoginPartial.cshtml" }, @@ -56,6 +52,15 @@ "Pages/Shared/_LoginPartial.Identity.cshtml" ] }, + { + "condition": "(IndividualLocalAuth)", + "rename": { + "Pages/Shared/_LoginPartial.Identity.cshtml": "Pages/Shared/_LoginPartial.cshtml" + }, + "exclude": [ + "Pages/Shared/_LoginPartial.OrgAuth.cshtml" + ] + }, { "condition": "(!IndividualLocalAuth || UseLocalDB)", "exclude": [ @@ -75,19 +80,6 @@ "Properties/launchSettings.json" ] }, - { - "condition": "(!OrganizationalAuth)", - "exclude": [ - "Extensions/AzureAdAuthenticationBuilderExtensions.cs", - "Extensions/AzureAdOptions.cs" - ] - }, - { - "condition": "(!IndividualB2CAuth)", - "exclude": [ - "Extensions/AzureAdB2C*.cs" - ] - }, { "condition": "(IndividualLocalAuth && UseLocalDB)", "rename": { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Controllers/AccountController.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Controllers/AccountController.cs deleted file mode 100644 index 763b5ed702..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Controllers/AccountController.cs +++ /dev/null @@ -1,88 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -#if (OrganizationalAuth || IndividualB2CAuth) -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -#endif -using Microsoft.AspNetCore.Mvc; -#if (IndividualB2CAuth) -using Microsoft.Extensions.Options; -#endif - -namespace Company.WebApplication1.Controllers -{ - [Route("[controller]/[action]")] - public class AccountController : Controller - { -#if (OrganizationalAuth) - [HttpGet] - public IActionResult SignIn() - { - var redirectUrl = Url.Page("/Index"); - return Challenge( - new AuthenticationProperties { RedirectUri = redirectUrl }, - OpenIdConnectDefaults.AuthenticationScheme - ); - } - - [HttpGet] - public IActionResult SignOut() - { - var callbackUrl = Url.Page("/Account/SignedOut", pageHandler: null, values: null, protocol: Request.Scheme); - return SignOut( - new AuthenticationProperties { RedirectUri = callbackUrl }, - CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme - ); - } -#elseif (IndividualB2CAuth) - private readonly AzureAdB2COptions _options; - - public AccountController(IOptions b2cOptions) - { - _options = b2cOptions.Value; - } - - [HttpGet] - public IActionResult SignIn() - { - var redirectUrl = Url.Page("/Index"); - return Challenge( - new AuthenticationProperties { RedirectUri = redirectUrl }, - OpenIdConnectDefaults.AuthenticationScheme - ); - } - - [HttpGet] - public IActionResult ResetPassword() - { - var redirectUrl = Url.Page("/Index"); - var properties = new AuthenticationProperties { RedirectUri = redirectUrl }; - properties.Items[AzureAdB2COptions.PolicyAuthenticationProperty] = _options.ResetPasswordPolicyId; - return Challenge(properties, OpenIdConnectDefaults.AuthenticationScheme); - } - - [HttpGet] - public IActionResult EditProfile() - { - var redirectUrl = Url.Page("/Index"); - var properties = new AuthenticationProperties { RedirectUri = redirectUrl }; - properties.Items[AzureAdB2COptions.PolicyAuthenticationProperty] = _options.EditProfilePolicyId; - return Challenge(properties, OpenIdConnectDefaults.AuthenticationScheme); - } - - [HttpGet] - public IActionResult SignOut() - { - var callbackUrl = Url.Page("/Account/SignedOut", pageHandler: null, values: null, protocol: Request.Scheme); - return SignOut( - new AuthenticationProperties { RedirectUri = callbackUrl }, - CookieAuthenticationDefaults.AuthenticationScheme, - OpenIdConnectDefaults.AuthenticationScheme - ); - } -#endif - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs deleted file mode 100644 index 82aea1a07e..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -#if (MultiOrgAuth) -using System.Threading.Tasks; -#endif -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -#if (MultiOrgAuth) -using Microsoft.IdentityModel.Protocols.OpenIdConnect; -using Microsoft.IdentityModel.Tokens; -#endif - -namespace Microsoft.AspNetCore.Authentication -{ - public static class AzureAdAuthenticationBuilderExtensions - { - public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder) - => builder.AddAzureAd(_ => { }); - - public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action configureOptions) - { - builder.Services.Configure(configureOptions); - builder.Services.AddSingleton, ConfigureAzureOptions>(); - builder.AddOpenIdConnect(); - return builder; - } - - private class ConfigureAzureOptions : IConfigureNamedOptions - { - private readonly AzureAdOptions _azureOptions; - - public ConfigureAzureOptions(IOptions azureOptions) - { - _azureOptions = azureOptions.Value; - } - - public void Configure(string name, OpenIdConnectOptions options) - { - options.ClientId = _azureOptions.ClientId; - options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}"; - options.UseTokenLifetime = true; - options.CallbackPath = _azureOptions.CallbackPath; - options.RequireHttpsMetadata = false; -#if (MultiOrgAuth) - - options.TokenValidationParameters = new TokenValidationParameters - { - // Instead of using the default validation (validating against a single issuer value, as we do in - // line of business apps), we inject our own multitenant validation logic - ValidateIssuer = false, - - // If the app is meant to be accessed by entire organizations, add your issuer validation logic here. - //IssuerValidator = (issuer, securityToken, validationParameters) => { - // if (myIssuerValidationLogic(issuer)) return issuer; - //} - }; - - options.Events = new OpenIdConnectEvents - { - OnTicketReceived = context => - { - // If your authentication logic is based on users then add your logic here - return Task.CompletedTask; - }, - OnAuthenticationFailed = context => - { - context.Response.Redirect("/Error"); - context.HandleResponse(); // Suppress the exception - return Task.CompletedTask; - }, - // If your application needs to do authenticate single users, add your user validation below. - //OnTokenValidated = context => - //{ - // return myUserValidationLogic(context.Ticket.Principal); - //} - }; -#endif - } - - public void Configure(OpenIdConnectOptions options) - { - Configure(Options.DefaultName, options); - } - } - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs deleted file mode 100644 index db7ed5227b..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using Microsoft.IdentityModel.Protocols.OpenIdConnect; -using Microsoft.IdentityModel.Tokens; - -namespace Microsoft.AspNetCore.Authentication -{ - public static class AzureAdB2CAuthenticationBuilderExtensions - { - public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder) - => builder.AddAzureAdB2C(_ => { }); - - public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder, Action configureOptions) - { - builder.Services.Configure(configureOptions); - builder.Services.AddSingleton, ConfigureAzureOptions>(); - builder.AddOpenIdConnect(); - return builder; - } - - private class ConfigureAzureOptions: IConfigureNamedOptions - { - private readonly AzureAdB2COptions _azureOptions; - - public ConfigureAzureOptions(IOptions azureOptions) - { - _azureOptions = azureOptions.Value; - } - - public void Configure(string name, OpenIdConnectOptions options) - { - options.ClientId = _azureOptions.ClientId; - options.Authority = $"{_azureOptions.Instance}/{_azureOptions.Domain}/{_azureOptions.SignUpSignInPolicyId}/v2.0"; - options.UseTokenLifetime = true; - options.CallbackPath = _azureOptions.CallbackPath; - - options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name" }; - - options.Events = new OpenIdConnectEvents - { - OnRedirectToIdentityProvider = OnRedirectToIdentityProvider, - OnRemoteFailure = OnRemoteFailure - }; - } - - public void Configure(OpenIdConnectOptions options) - { - Configure(Options.DefaultName, options); - } - - public Task OnRedirectToIdentityProvider(RedirectContext context) - { - var defaultPolicy = _azureOptions.DefaultPolicy; - if (context.Properties.Items.TryGetValue(AzureAdB2COptions.PolicyAuthenticationProperty, out var policy) && - !policy.Equals(defaultPolicy)) - { - context.ProtocolMessage.Scope = OpenIdConnectScope.OpenIdProfile; - context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken; - context.ProtocolMessage.IssuerAddress = context.ProtocolMessage.IssuerAddress.ToLower() - .Replace($"/{defaultPolicy.ToLower()}/", $"/{policy.ToLower()}/"); - context.Properties.Items.Remove(AzureAdB2COptions.PolicyAuthenticationProperty); - } - return Task.CompletedTask; - } - - public Task OnRemoteFailure(RemoteFailureContext context) - { - context.HandleResponse(); - // Handle the error code that Azure AD B2C throws when trying to reset a password from the login page - // because password reset is not supported by a "sign-up or sign-in policy" - if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("AADB2C90118")) - { - // If the user clicked the reset password link, redirect to the reset password route - context.Response.Redirect("/Account/ResetPassword"); - } - else if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("access_denied")) - { - context.Response.Redirect("/"); - } - else - { - context.Response.Redirect("/Error"); - } - return Task.CompletedTask; - } - } - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdB2COptions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdB2COptions.cs deleted file mode 100644 index d998d3037a..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdB2COptions.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Microsoft.AspNetCore.Authentication -{ - public class AzureAdB2COptions - { - public const string PolicyAuthenticationProperty = "Policy"; - - public string ClientId { get; set; } - - public string Instance { get; set; } - - public string Domain { get; set; } - - public string EditProfilePolicyId { get; set; } - - public string SignUpSignInPolicyId { get; set; } - - public string ResetPasswordPolicyId { get; set; } - - public string CallbackPath { get; set; } - - public string DefaultPolicy => SignUpSignInPolicyId; - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdOptions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdOptions.cs deleted file mode 100644 index e7cb904256..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Extensions/AzureAdOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Microsoft.AspNetCore.Authentication -{ - public class AzureAdOptions - { - public string ClientId { get; set; } - - public string ClientSecret { get; set; } - - public string Instance { get; set; } - - public string Domain { get; set; } - - public string TenantId { get; set; } - - public string CallbackPath { get; set; } - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/AccessDenied.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/AccessDenied.cshtml deleted file mode 100644 index cc15816741..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/AccessDenied.cshtml +++ /dev/null @@ -1,10 +0,0 @@ -@page -@model AccessDeniedModel -@{ - ViewData["Title"] = "Access denied"; -} - -
-

@ViewData["Title"]

-

You do not have access to this resource.

-
\ No newline at end of file diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/AccessDenied.cshtml.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/AccessDenied.cshtml.cs deleted file mode 100644 index b5ed3d9c4a..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/AccessDenied.cshtml.cs +++ /dev/null @@ -1,11 +0,0 @@ -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace Company.WebApplication1.Pages.Account -{ - public class AccessDeniedModel : PageModel - { - public void OnGet() - { - } - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/SignedOut.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/SignedOut.cshtml deleted file mode 100644 index 66ee2c8595..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/SignedOut.cshtml +++ /dev/null @@ -1,10 +0,0 @@ -@page -@model SignedOutModel -@{ - ViewData["Title"] = "Signed out"; -} - -

@ViewData["Title"]

-

- You have successfully signed out. -

diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/SignedOut.cshtml.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/SignedOut.cshtml.cs deleted file mode 100644 index e364f34001..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Account/SignedOut.cshtml.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc; -using Microsoft.AspNetCore.Mvc.RazorPages; - -namespace Company.WebApplication1.Pages.Account -{ - public class SignedOutModel : PageModel - { - public IActionResult OnGet() - { - if (User.Identity.IsAuthenticated) - { - // Redirect to home page if the user is authenticated. - return RedirectToPage("/Index"); - } - - return Page(); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Shared/_LoginPartial.OrgAuth.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Shared/_LoginPartial.OrgAuth.cshtml index ed87a8899e..124a84495c 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Shared/_LoginPartial.OrgAuth.cshtml +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/Shared/_LoginPartial.OrgAuth.cshtml @@ -1,34 +1,47 @@ -@using System.Security.Principal @*#if (IndividualB2CAuth) -@using Microsoft.AspNetCore.Authentication +@using Microsoft.AspNetCore.Authentication.AzureADB2C.UI @using Microsoft.Extensions.Options -@inject IOptions AzureAdB2COptions +@inject IOptionsMonitor AzureADB2COptions + +@{ + var options = AzureADB2COptions.Get(AzureADB2CDefaults.AuthenticationScheme); +} + #endif *@ +@*#if (IndividualB2CAuth) @if (User.Identity.IsAuthenticated) { -@*#if (IndividualB2CAuth) -#else - -#endif *@ } else { } +#else +@if (User.Identity.IsAuthenticated) +{ + +} +else +{ + +} +#endif *@ \ No newline at end of file diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/_ViewImports.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/_ViewImports.cshtml index 62bba96564..7fdcd89164 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/_ViewImports.cshtml +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Pages/_ViewImports.cshtml @@ -5,8 +5,5 @@ @*#if (IndividualLocalAuth) @using Company.WebApplication1.Data #endif*@ -@*#if (OrganizationalAuth || IndividualB2CAuth) -@using Company.WebApplication1.Pages.Account -#endif*@ @namespace Company.WebApplication1.Pages @addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Startup.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Startup.cs index 458722e4d5..764d8c111b 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Startup.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/content/RazorPagesWeb-CSharp/Startup.cs @@ -4,12 +4,17 @@ using System.Linq; using System.Threading.Tasks; #if (OrganizationalAuth || IndividualB2CAuth) using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authentication.OpenIdConnect; #endif #if (OrganizationalAuth) +using Microsoft.AspNetCore.Authentication.AzureAD.UI; +#if (MultiOrgAuth) +using Microsoft.AspNetCore.Authentication.OpenIdConnect; +#endif using Microsoft.AspNetCore.Authorization; #endif +#if (IndividualB2CAuth) +using Microsoft.AspNetCore.Authentication.AzureADB2C.UI; +#endif using Microsoft.AspNetCore.Builder; #if (IndividualLocalAuth) using Microsoft.AspNetCore.Identity; @@ -27,10 +32,7 @@ using Company.WebApplication1.Data; #endif using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -#if (OrganizationalAuth && OrgReadAccess) -using Microsoft.IdentityModel.Protocols.OpenIdConnect; -#endif -#if (MultiOrgAuth) +#if(MultiOrgAuth) using Microsoft.IdentityModel.Tokens; #endif @@ -57,30 +59,61 @@ namespace Company.WebApplication1 #if (IndividualLocalAuth) services.AddDbContext(options => -#if (UseLocalDB) + #if (UseLocalDB) options.UseSqlServer( Configuration.GetConnectionString("DefaultConnection"))); -#else + #else options.UseSqlite( Configuration.GetConnectionString("DefaultConnection"))); -#endif + #endif services.AddDefaultIdentity() .AddEntityFrameworkStores(); -#elif (OrganizationalAuth || IndividualB2CAuth) - services.AddAuthentication(sharedOptions => - { - sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; - sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; - }) -#if (OrganizationalAuth) - .AddAzureAd(options => Configuration.Bind("AzureAd", options)) -#elif (IndividualB2CAuth) - .AddAzureAdB2C(options => Configuration.Bind("AzureAdB2C", options)) -#endif - .AddCookie(); +#elif (OrganizationalAuth) + services.AddAuthentication(AzureADDefaults.AuthenticationScheme) + .AddAzureAD(options => Configuration.Bind("AzureAd", options)); +#if (MultiOrgAuth) + services.Configure(AzureADDefaults.OpenIdScheme, options => + { + options.TokenValidationParameters = new TokenValidationParameters + { + // Instead of using the default validation (validating against a single issuer value, as we do in + // line of business apps), we inject our own multitenant validation logic + ValidateIssuer = false, + + // If the app is meant to be accessed by entire organizations, add your issuer validation logic here. + //IssuerValidator = (issuer, securityToken, validationParameters) => { + // if (myIssuerValidationLogic(issuer)) return issuer; + //} + }; + + options.Events = new OpenIdConnectEvents + { + OnTicketReceived = context => + { + // If your authentication logic is based on users then add your logic here + return Task.CompletedTask; + }, + OnAuthenticationFailed = context => + { + context.Response.Redirect("/Error"); + context.HandleResponse(); // Suppress the exception + return Task.CompletedTask; + }, + // If your application needs to do authenticate single users, add your user validation below. + //OnTokenValidated = context => + //{ + // return myUserValidationLogic(context.Ticket.Principal); + //} + }; + }); #endif +#elif (IndividualB2CAuth) + services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme) + .AddAzureADB2C(options => Configuration.Bind("AzureAdB2C", options)); +#endif + #if (OrganizationalAuth) services.AddMvc(options => { @@ -89,10 +122,6 @@ namespace Company.WebApplication1 .Build(); options.Filters.Add(new AuthorizeFilter(policy)); }) - .AddRazorPagesOptions(options => - { - options.Conventions.AllowAnonymousToFolder("/Account"); - }) .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); #else services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/template.json b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/template.json index ef0d11fb47..e033a4fdb2 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/template.json +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/.template.config/template.json @@ -36,21 +36,38 @@ ] }, { - "condition": "(!IndividualAuth && !OrganizationalAuth && !IndividualB2CAuth)", + "condition": "(!OrganizationalAuth && !IndividualAuth)", "exclude": [ - "Controllers/AccountController.cs", - "Views/Account/**", - "Views/Shared/_LoginPartial.cshtml" + "Views/Shared/_LoginPartial.Identity.cshtml", + "Views/Shared/_LoginPartial.OrgAuth.cshtml" ] }, { - "condition": "(!IndividualAuth || UseLocalDB)", + "condition": "(OrganizationalAuth || IndividualB2CAuth)", + "rename": { + "Views/Shared/_LoginPartial.OrgAuth.cshtml": "Views/Shared/_LoginPartial.cshtml" + }, + "exclude": [ + "Views/Shared/_LoginPartial.Identity.cshtml" + ] + }, + { + "condition": "(IndividualLocalAuth)", + "rename": { + "Views/Shared/_LoginPartial.Identity.cshtml": "Views/Shared/_LoginPartial.cshtml" + }, + "exclude": [ + "Views/Shared/_LoginPartial.OrgAuth.cshtml" + ] + }, + { + "condition": "(!IndividualLocalAuth || UseLocalDB)", "exclude": [ "app.db" ] }, { - "condition": "(!IndividualAuth)", + "condition": "(!IndividualLocalAuth)", "exclude": [ "Data/**", "Areas/**" @@ -62,31 +79,10 @@ "Properties/launchSettings.json" ] }, - { - "condition": "(IndividualLocalAuth)", - "exclude": [ - "Controllers/AccountController.cs", - "Views/Account/**" - ] - }, - { - "condition": "(!OrganizationalAuth)", - "exclude": [ - "Extensions/AzureAdAuthenticationBuilderExtensions.cs", - "Extensions/AzureAdOptions.cs" - ] - }, - { - "condition": "(!IndividualB2CAuth)", - "exclude": [ - "Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs", - "Extensions/AzureAdB2COptions.cs" - ] - }, { "condition": "(IndividualLocalAuth && UseLocalDB)", "rename": { - "Data/SqlServer/": "Data/Migrations/", + "Data/SqlServer/": "Data/Migrations/" }, "exclude": [ "Data/SqlLite/**" diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Controllers/AccountController.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Controllers/AccountController.cs deleted file mode 100644 index 9e5140cc01..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Controllers/AccountController.cs +++ /dev/null @@ -1,117 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -#if (OrganizationalAuth || IndividualB2CAuth) -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -#endif -using Microsoft.AspNetCore.Mvc; -#if (IndividualB2CAuth) -using Microsoft.Extensions.Options; -#endif - -namespace Company.WebApplication1.Controllers -{ - [Route("[controller]/[action]")] - public class AccountController : Controller - { -#if (OrganizationalAuth) - [HttpGet] - public IActionResult SignIn() - { - var redirectUrl = Url.Action(nameof(HomeController.Index), "Home"); - return Challenge( - new AuthenticationProperties { RedirectUri = redirectUrl }, - OpenIdConnectDefaults.AuthenticationScheme - ); - } - - [HttpGet] - public IActionResult SignOut() - { - var callbackUrl = Url.Action(nameof(SignedOut), "Account", values: null, protocol: Request.Scheme); - return SignOut( - new AuthenticationProperties { RedirectUri = callbackUrl }, - CookieAuthenticationDefaults.AuthenticationScheme, OpenIdConnectDefaults.AuthenticationScheme - ); - } - - [HttpGet] - public IActionResult SignedOut() - { - if (User.Identity.IsAuthenticated) - { - // Redirect to home page if the user is authenticated. - return RedirectToAction(nameof(HomeController.Index), "Home"); - } - - return View(); - } -#elseif (IndividualB2CAuth) - private readonly AzureAdB2COptions _options; - - public AccountController(IOptions b2cOptions) - { - _options = b2cOptions.Value; - } - - [HttpGet] - public IActionResult SignIn() - { - var redirectUrl = Url.Action(nameof(HomeController.Index), "Home"); - return Challenge( - new AuthenticationProperties { RedirectUri = redirectUrl }, - OpenIdConnectDefaults.AuthenticationScheme - ); - } - - [HttpGet] - public IActionResult ResetPassword() - { - var redirectUrl = Url.Action(nameof(HomeController.Index), "Home"); - var properties = new AuthenticationProperties { RedirectUri = redirectUrl }; - properties.Items[AzureAdB2COptions.PolicyAuthenticationProperty] = _options.ResetPasswordPolicyId; - return Challenge(properties, OpenIdConnectDefaults.AuthenticationScheme); - } - - [HttpGet] - public IActionResult EditProfile() - { - var redirectUrl = Url.Action(nameof(HomeController.Index), "Home"); - var properties = new AuthenticationProperties { RedirectUri = redirectUrl }; - properties.Items[AzureAdB2COptions.PolicyAuthenticationProperty] = _options.EditProfilePolicyId; - return Challenge(properties, OpenIdConnectDefaults.AuthenticationScheme); - } - - [HttpGet] - public IActionResult SignOut() - { - var callbackUrl = Url.Action(nameof(SignedOut), "Account", values: null, protocol: Request.Scheme); - return SignOut( - new AuthenticationProperties { RedirectUri = callbackUrl }, - CookieAuthenticationDefaults.AuthenticationScheme, - OpenIdConnectDefaults.AuthenticationScheme); - } - - [HttpGet] - public IActionResult SignedOut() - { - if (User.Identity.IsAuthenticated) - { - // Redirect to home page if the user is authenticated. - return RedirectToAction(nameof(HomeController.Index), "Home"); - } - - return View(); - } -#endif - - [HttpGet] - public IActionResult AccessDenied() - { - return View(); - } - } -} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs deleted file mode 100644 index e6060f7f12..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs +++ /dev/null @@ -1,87 +0,0 @@ -using System; -#if (MultiOrgAuth) -using System.Threading.Tasks; -#endif -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -#if (MultiOrgAuth) -using Microsoft.IdentityModel.Protocols.OpenIdConnect; -using Microsoft.IdentityModel.Tokens; -#endif - -namespace Microsoft.AspNetCore.Authentication -{ - public static class AzureAdAuthenticationBuilderExtensions - { - public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder) - => builder.AddAzureAd(_ => { }); - - public static AuthenticationBuilder AddAzureAd(this AuthenticationBuilder builder, Action configureOptions) - { - builder.Services.Configure(configureOptions); - builder.Services.AddSingleton, ConfigureAzureOptions>(); - builder.AddOpenIdConnect(); - return builder; - } - - private class ConfigureAzureOptions: IConfigureNamedOptions - { - private readonly AzureAdOptions _azureOptions; - - public ConfigureAzureOptions(IOptions azureOptions) - { - _azureOptions = azureOptions.Value; - } - - public void Configure(string name, OpenIdConnectOptions options) - { - options.ClientId = _azureOptions.ClientId; - options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}"; - options.UseTokenLifetime = true; - options.CallbackPath = _azureOptions.CallbackPath; - options.RequireHttpsMetadata = false; -#if (MultiOrgAuth) - - options.TokenValidationParameters = new TokenValidationParameters - { - // Instead of using the default validation (validating against a single issuer value, as we do in line of business apps), - // we inject our own multitenant validation logic - ValidateIssuer = false, - - // If the app is meant to be accessed by entire organizations, add your issuer validation logic here. - //IssuerValidator = (issuer, securityToken, validationParameters) => { - // if (myIssuerValidationLogic(issuer)) return issuer; - //} - }; - - options.Events = new OpenIdConnectEvents - { - OnTicketReceived = context => - { - // If your authentication logic is based on users then add your logic here - return Task.CompletedTask; - }, - OnAuthenticationFailed = context => - { - context.Response.Redirect("/Home/Error"); - context.HandleResponse(); // Suppress the exception - return Task.CompletedTask; - }, - // If your application needs to do authenticate single users, add your user validation below. - //OnTokenValidated = context => - //{ - // return myUserValidationLogic(context.Ticket.Principal); - //} - }; -#endif - } - - public void Configure(OpenIdConnectOptions options) - { - Configure(Options.DefaultName, options); - } - } - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs deleted file mode 100644 index acfff43fd9..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs +++ /dev/null @@ -1,91 +0,0 @@ -using System; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Authentication.OpenIdConnect; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; -using Microsoft.IdentityModel.Protocols.OpenIdConnect; -using Microsoft.IdentityModel.Tokens; - -namespace Microsoft.AspNetCore.Authentication -{ - public static class AzureAdB2CAuthenticationBuilderExtensions - { - public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder) - => builder.AddAzureAdB2C(_ => { }); - - public static AuthenticationBuilder AddAzureAdB2C(this AuthenticationBuilder builder, Action configureOptions) - { - builder.Services.Configure(configureOptions); - builder.Services.AddSingleton, ConfigureAzureOptions>(); - builder.AddOpenIdConnect(); - return builder; - } - - private class ConfigureAzureOptions: IConfigureNamedOptions - { - private readonly AzureAdB2COptions _azureOptions; - - public ConfigureAzureOptions(IOptions azureOptions) - { - _azureOptions = azureOptions.Value; - } - - public void Configure(string name, OpenIdConnectOptions options) - { - options.ClientId = _azureOptions.ClientId; - options.Authority = $"{_azureOptions.Instance}/{_azureOptions.Domain}/{_azureOptions.SignUpSignInPolicyId}/v2.0"; - options.UseTokenLifetime = true; - options.CallbackPath = _azureOptions.CallbackPath; - - options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name" }; - - options.Events = new OpenIdConnectEvents - { - OnRedirectToIdentityProvider = OnRedirectToIdentityProvider, - OnRemoteFailure = OnRemoteFailure - }; - } - - public void Configure(OpenIdConnectOptions options) - { - Configure(Options.DefaultName, options); - } - - public Task OnRedirectToIdentityProvider(RedirectContext context) - { - var defaultPolicy = _azureOptions.DefaultPolicy; - if (context.Properties.Items.TryGetValue(AzureAdB2COptions.PolicyAuthenticationProperty, out var policy) && - !policy.Equals(defaultPolicy)) - { - context.ProtocolMessage.Scope = OpenIdConnectScope.OpenIdProfile; - context.ProtocolMessage.ResponseType = OpenIdConnectResponseType.IdToken; - context.ProtocolMessage.IssuerAddress = context.ProtocolMessage.IssuerAddress.ToLower() - .Replace($"/{defaultPolicy.ToLower()}/", $"/{policy.ToLower()}/"); - context.Properties.Items.Remove(AzureAdB2COptions.PolicyAuthenticationProperty); - } - return Task.CompletedTask; - } - - public Task OnRemoteFailure(RemoteFailureContext context) - { - context.HandleResponse(); - // Handle the error code that Azure AD B2C throws when trying to reset a password from the login page - // because password reset is not supported by a "sign-up or sign-in policy" - if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("AADB2C90118")) - { - // If the user clicked the reset password link, redirect to the reset password route - context.Response.Redirect("/Account/ResetPassword"); - } - else if (context.Failure is OpenIdConnectProtocolException && context.Failure.Message.Contains("access_denied")) - { - context.Response.Redirect("/"); - } - else - { - context.Response.Redirect("/Home/Error"); - } - return Task.CompletedTask; - } - } - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdB2COptions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdB2COptions.cs deleted file mode 100644 index ea8c53297a..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdB2COptions.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Microsoft.AspNetCore.Authentication -{ - public class AzureAdB2COptions - { - public const string PolicyAuthenticationProperty = "Policy"; - - public string ClientId { get; set; } - - public string Instance { get; set; } - - public string Domain { get; set; } - - public string EditProfilePolicyId { get; set; } - - public string SignUpSignInPolicyId { get; set; } - - public string ResetPasswordPolicyId { get; set; } - - public string CallbackPath { get; set; } - - public string DefaultPolicy => SignUpSignInPolicyId; - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdOptions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdOptions.cs deleted file mode 100644 index 17fd16aa9e..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Extensions/AzureAdOptions.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Microsoft.AspNetCore.Authentication -{ - public class AzureAdOptions - { - public string ClientId { get; set; } - - public string ClientSecret { get; set; } - - public string Instance { get; set; } - - public string Domain { get; set; } - - public string TenantId { get; set; } - - public string CallbackPath { get; set; } - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Startup.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Startup.cs index 0b9cb321a9..411efe599d 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Startup.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Startup.cs @@ -4,9 +4,17 @@ using System.Linq; using System.Threading.Tasks; #if (OrganizationalAuth || IndividualB2CAuth) using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.Cookies; +#endif +#if (OrganizationalAuth) +using Microsoft.AspNetCore.Authentication.AzureAD.UI; +#if (MultiOrgAuth) using Microsoft.AspNetCore.Authentication.OpenIdConnect; #endif +using Microsoft.AspNetCore.Authorization; +#endif +#if (IndividualB2CAuth) +using Microsoft.AspNetCore.Authentication.AzureADB2C.UI; +#endif using Microsoft.AspNetCore.Builder; #if (IndividualLocalAuth) using Microsoft.AspNetCore.Identity; @@ -15,16 +23,16 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; +#if (OrganizationalAuth) +using Microsoft.AspNetCore.Mvc.Authorization; +#endif #if (IndividualLocalAuth) using Microsoft.EntityFrameworkCore; using Company.WebApplication1.Data; #endif using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; -#if (OrganizationalAuth && OrgReadAccess) -using Microsoft.IdentityModel.Protocols.OpenIdConnect; -#endif -#if (MultiOrgAuth) +#if(MultiOrgAuth) using Microsoft.IdentityModel.Tokens; #endif @@ -42,6 +50,13 @@ namespace Company.WebApplication1 // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { + services.Configure(options => + { + // This lambda determines whether user consent for non-essential cookies is needed for a given request. + options.CheckConsentNeeded = context => true; + options.MinimumSameSitePolicy = SameSiteMode.None; + }); + #if (IndividualLocalAuth) services.AddDbContext(options => #if (UseLocalDB) @@ -51,32 +66,65 @@ namespace Company.WebApplication1 options.UseSqlite( Configuration.GetConnectionString("DefaultConnection"))); #endif - services.AddDefaultIdentity() .AddEntityFrameworkStores(); +#elif (OrganizationalAuth) + services.AddAuthentication(AzureADDefaults.AuthenticationScheme) + .AddAzureAD(options => Configuration.Bind("AzureAd", options)); +#if (MultiOrgAuth) -#elif (OrganizationalAuth || IndividualB2CAuth) - services.AddAuthentication(sharedOptions => + services.Configure(AzureADDefaults.OpenIdScheme, options => { - sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; - sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme; - }) - #if (OrganizationalAuth) - .AddAzureAd(options => Configuration.Bind("AzureAd", options)) - #elif (IndividualB2CAuth) - .AddAzureAdB2C(options => Configuration.Bind("AzureAdB2C", options)) - #endif - .AddCookie(); + options.TokenValidationParameters = new TokenValidationParameters + { + // Instead of using the default validation (validating against a single issuer value, as we do in + // line of business apps), we inject our own multitenant validation logic + ValidateIssuer = false, -#endif - services.Configure(options => - { - // This lambda determines whether user consent for non-essential cookies is needed for a given request. - options.CheckConsentNeeded = context => true; - options.MinimumSameSitePolicy = SameSiteMode.None; + // If the app is meant to be accessed by entire organizations, add your issuer validation logic here. + //IssuerValidator = (issuer, securityToken, validationParameters) => { + // if (myIssuerValidationLogic(issuer)) return issuer; + //} + }; + + options.Events = new OpenIdConnectEvents + { + OnTicketReceived = context => + { + // If your authentication logic is based on users then add your logic here + return Task.CompletedTask; + }, + OnAuthenticationFailed = context => + { + context.Response.Redirect("/Error"); + context.HandleResponse(); // Suppress the exception + return Task.CompletedTask; + }, + // If your application needs to do authenticate single users, add your user validation below. + //OnTokenValidated = context => + //{ + // return myUserValidationLogic(context.Ticket.Principal); + //} + }; }); +#endif +#elif (IndividualB2CAuth) + services.AddAuthentication(AzureADB2CDefaults.AuthenticationScheme) + .AddAzureADB2C(options => Configuration.Bind("AzureAdB2C", options)); +#endif + #if (OrganizationalAuth) + services.AddMvc(options => + { + var policy = new AuthorizationPolicyBuilder() + .RequireAuthenticatedUser() + .Build(); + options.Filters.Add(new AuthorizeFilter(policy)); + }) + .SetCompatibilityVersion(CompatibilityVersion.Version_2_1); +#else services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); +#endif } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Account/AccessDenied.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Account/AccessDenied.cshtml deleted file mode 100644 index c27d3daeb3..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Account/AccessDenied.cshtml +++ /dev/null @@ -1,8 +0,0 @@ -@{ - ViewData["Title"] = "Access denied"; -} - -
-

@ViewData["Title"]

-

You do not have access to this resource.

-
diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Account/SignedOut.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Account/SignedOut.cshtml deleted file mode 100644 index c7fb988cd4..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Account/SignedOut.cshtml +++ /dev/null @@ -1,8 +0,0 @@ -@{ - ViewData["Title"] = "Signed out"; -} - -

@ViewData["Title"]

-

- You have successfully signed out. -

diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.Identity.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.Identity.cshtml new file mode 100644 index 0000000000..3cd78ca58a --- /dev/null +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.Identity.cshtml @@ -0,0 +1,25 @@ +@using Microsoft.AspNetCore.Identity + +@inject SignInManager SignInManager +@inject UserManager UserManager + +@if (SignInManager.IsSignedIn(User)) +{ + +} +else +{ + +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.OrgAuth.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.OrgAuth.cshtml new file mode 100644 index 0000000000..37e437dc07 --- /dev/null +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.OrgAuth.cshtml @@ -0,0 +1,48 @@ +@using System.Security.Principal +@*#if (IndividualB2CAuth) +@using Microsoft.AspNetCore.Authentication.AzureADB2C.UI +@using Microsoft.Extensions.Options +@inject IOptionsMonitor AzureADB2COptions + +@{ + var options = AzureADB2COptions.Get(AzureADB2CDefaults.AuthenticationScheme); +} + +#endif *@ + +@*#if (IndividualB2CAuth) +@if (User.Identity.IsAuthenticated) +{ + +} +else +{ + +} +#else +@if (User.Identity.IsAuthenticated) +{ + +} +else +{ + +} +#endif *@ \ No newline at end of file diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.cshtml deleted file mode 100644 index bd3b8aa45e..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.cshtml +++ /dev/null @@ -1,67 +0,0 @@ -@*#if (IndividualB2CAuth) -@using Microsoft.AspNetCore.Authentication -@using Microsoft.Extensions.Options - -#endif -@*#if (IndividualB2CAuth) -@inject IOptions AzureAdB2COptions - -#endif *@ -@*#if (IndividualLocalAuth) *@ -@using Microsoft.AspNetCore.Identity -@*#else -@using System.Security.Principal -#endif *@ - -@*#if (IndividualLocalAuth) *@ -@inject SignInManager SignInManager -@inject UserManager UserManager -@*#endif *@ -@*#if (IndividualLocalAuth) *@ - -@if (SignInManager.IsSignedIn(User)) -@*#else -@if (User.Identity.IsAuthenticated) -#endif *@ -{ -@*#if (IndividualLocalAuth) *@ - -@*#elseif (IndividualB2CAuth) - -#else - -#endif *@ -} -else -{ - -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/.template.config/template.json b/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/.template.config/template.json index c5cd267f7b..aeebdf293e 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/.template.config/template.json +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/.template.config/template.json @@ -43,20 +43,6 @@ "exclude": [ "Properties/launchSettings.json" ] - }, - { - "condition": "(!OrganizationalAuth)", - "exclude": [ - "Extensions/AzureAdAuthenticationBuilderExtensions.cs", - "Extensions/AzureAdOptions.cs" - ] - }, - { - "condition": "(!IndividualB2CAuth)", - "exclude": [ - "Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs", - "Extensions/AzureAdB2COptions.cs" - ] } ] } diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs deleted file mode 100644 index b8c4e08f0b..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdAuthenticationBuilderExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.Authentication -{ - public static class AzureAdServiceCollectionExtensions - { - public static AuthenticationBuilder AddAzureAdBearer(this AuthenticationBuilder builder) - => builder.AddAzureAdBearer(_ => { }); - - public static AuthenticationBuilder AddAzureAdBearer(this AuthenticationBuilder builder, Action configureOptions) - { - builder.Services.Configure(configureOptions); - builder.Services.AddSingleton, ConfigureAzureOptions>(); - builder.AddJwtBearer(); - return builder; - } - - private class ConfigureAzureOptions: IConfigureNamedOptions - { - private readonly AzureAdOptions _azureOptions; - - public ConfigureAzureOptions(IOptions azureOptions) - { - _azureOptions = azureOptions.Value; - } - - public void Configure(string name, JwtBearerOptions options) - { - options.Audience = _azureOptions.ClientId; - options.Authority = $"{_azureOptions.Instance}{_azureOptions.TenantId}"; - } - - public void Configure(JwtBearerOptions options) - { - Configure(Options.DefaultName, options); - } - } - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs deleted file mode 100644 index 62e5c580d0..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdB2CAuthenticationBuilderExtensions.cs +++ /dev/null @@ -1,43 +0,0 @@ -using System; -using Microsoft.AspNetCore.Authentication.JwtBearer; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Options; - -namespace Microsoft.AspNetCore.Authentication -{ - public static class AzureAdServiceCollectionExtensions - { - public static AuthenticationBuilder AddAzureAdB2CBearer(this AuthenticationBuilder builder) - => builder.AddAzureAdB2CBearer(_ => { }); - - public static AuthenticationBuilder AddAzureAdB2CBearer(this AuthenticationBuilder builder, Action configureOptions) - { - builder.Services.Configure(configureOptions); - builder.Services.AddSingleton, ConfigureAzureOptions>(); - builder.AddJwtBearer(); - return builder; - } - - private class ConfigureAzureOptions: IConfigureNamedOptions - { - private readonly AzureAdB2COptions _azureOptions; - - public ConfigureAzureOptions(IOptions azureOptions) - { - _azureOptions = azureOptions.Value; - } - - public void Configure(string name, JwtBearerOptions options) - { - options.Audience = _azureOptions.ClientId; - options.Authority = $"{_azureOptions.Instance}/{_azureOptions.Domain}/{_azureOptions.SignUpSignInPolicyId}/v2.0"; - } - - public void Configure(JwtBearerOptions options) - { - Configure(Options.DefaultName, options); - } - } - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdB2COptions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdB2COptions.cs deleted file mode 100644 index 11c46c5592..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdB2COptions.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Microsoft.AspNetCore.Authentication -{ - public class AzureAdB2COptions - { - public string ClientId { get; set; } - public string Instance { get; set; } - public string Domain { get; set; } - public string SignUpSignInPolicyId { get; set; } - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdOptions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdOptions.cs deleted file mode 100644 index 8a2b051165..0000000000 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Extensions/AzureAdOptions.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Microsoft.AspNetCore.Authentication -{ - public class AzureAdOptions - { - public string ClientId { get; set; } - public string ClientSecret { get; set; } - public string Instance { get; set; } - public string Domain { get; set; } - public string TenantId { get; set; } - } -} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Startup.cs b/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Startup.cs index 42991cd568..58301e692e 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Startup.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates/content/WebApi-CSharp/Startup.cs @@ -8,7 +8,12 @@ using Microsoft.AspNetCore.HttpsPolicy; using Microsoft.AspNetCore.Mvc; #if (OrganizationalAuth || IndividualB2CAuth) using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Authentication.JwtBearer; +#endif +#if (OrganizationalAuth) +using Microsoft.AspNetCore.Authentication.AzureAD.UI; +#endif +#if (IndividualB2CAuth) +using Microsoft.AspNetCore.Authentication.AzureADB2C.UI; #endif using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; @@ -29,17 +34,12 @@ namespace Company.WebApplication1 // This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { -#if (OrganizationalAuth || IndividualB2CAuth) - services.AddAuthentication(sharedOptions => - { - sharedOptions.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; - }) - #if (IndividualB2CAuth) - .AddAzureAdB2CBearer(options => Configuration.Bind("AzureAdB2C", options)); - #elif (OrganizationalAuth) - .AddAzureAdBearer(options => Configuration.Bind("AzureAd", options)); - #endif - +#if (OrganizationalAuth) + services.AddAuthentication(AzureADDefaults.BearerAuthenticationScheme) + .AddAzureADBearer(options => Configuration.Bind("AzureAd", options)); +#elif (IndividualB2CAuth) + services.AddAuthentication(AzureADB2CDefaults.BearerAuthenticationScheme) + .AddAzureADB2CBearer(options => Configuration.Bind("AzureAdB2C", options)); #endif services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1); } diff --git a/test/Templates.Test/.gitattributes b/test/Templates.Test/.gitattributes new file mode 100644 index 0000000000..300e504f3e --- /dev/null +++ b/test/Templates.Test/.gitattributes @@ -0,0 +1 @@ +.json diff \ No newline at end of file diff --git a/test/Templates.Test/BaselineTest.cs b/test/Templates.Test/BaselineTest.cs new file mode 100644 index 0000000000..d39ca267b0 --- /dev/null +++ b/test/Templates.Test/BaselineTest.cs @@ -0,0 +1,73 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.IO; +using System.Linq; +using Microsoft.AspNetCore.Testing.xunit; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Xunit; +using Xunit.Abstractions; + +namespace Templates.Test +{ + public class BaselineTest : TemplateTestBase + { + public BaselineTest(ITestOutputHelper output) : base(output) + { + } + + public static TheoryData TemplateBaselines + { + get + { + using (var stream = typeof(BaselineTest).Assembly.GetManifestResourceStream("Templates.Test.template-baselines.json")) + { + using (var jsonReader = new JsonTextReader(new StreamReader(stream))) + { + var baseline = JObject.Load(jsonReader); + var data = new TheoryData(); + foreach (var template in baseline) + { + foreach (var authOption in (JObject)template.Value) + { + data.Add( + (string)authOption.Value["Arguments"], + ((JArray)authOption.Value["Files"]).Select(s => (string)s).ToArray()); + } + } + + return data; + } + } + } + } + + [Theory] + [MemberData(nameof(TemplateBaselines))] + public void Template_Produces_The_Right_Set_Of_Files(string arguments, string[] expectedFiles) + { + RunDotNet(arguments); + foreach (var file in expectedFiles) + { + AssertFileExists(file, shouldExist: true); + } + + var filesInFolder = Directory.EnumerateFiles(TemplateOutputDir, "*", SearchOption.AllDirectories); + foreach (var file in filesInFolder) + { + var relativePath = file.Replace(TemplateOutputDir, "").Replace("\\", "/").Trim('/'); + if (relativePath.EndsWith(".csproj", StringComparison.Ordinal) || + relativePath.EndsWith(".props", StringComparison.Ordinal) || + relativePath.EndsWith(".targets", StringComparison.Ordinal) || + relativePath.StartsWith("bin/", StringComparison.Ordinal) || + relativePath.StartsWith("obj/", StringComparison.Ordinal)) + { + continue; + } + Assert.Contains(relativePath, expectedFiles); + } + } + } +} diff --git a/test/Templates.Test/Helpers/TemplateTestBase.cs b/test/Templates.Test/Helpers/TemplateTestBase.cs index b42eba6ae3..0d7c444dad 100644 --- a/test/Templates.Test/Helpers/TemplateTestBase.cs +++ b/test/Templates.Test/Helpers/TemplateTestBase.cs @@ -19,7 +19,7 @@ namespace Templates.Test protected string ProjectName { get; set; } protected string ProjectGuid { get; set; } - protected string TemplateOutputDir { get; private set; } + protected string TemplateOutputDir { get; set; } protected ITestOutputHelper Output { get; private set; } public TemplateTestBase(ITestOutputHelper output) @@ -80,6 +80,14 @@ namespace Templates.Test } } + protected void RunDotNet(string arguments) + { + lock (DotNetNewLock) + { + ProcessEx.Run(Output, TemplateOutputDir, DotNetMuxer.MuxerPathOrDefault(), arguments).WaitForExit(assertSuccess: true); + } + } + protected void RunDotNetEfCreateMigration(string migrationName) { var args = $"ef migrations add {migrationName}"; diff --git a/test/Templates.Test/Templates.Test.csproj b/test/Templates.Test/Templates.Test.csproj index 6e699e9215..21fbb6e9de 100644 --- a/test/Templates.Test/Templates.Test.csproj +++ b/test/Templates.Test/Templates.Test.csproj @@ -5,6 +5,10 @@ $(DefineConstants);XPLAT
+ + + + diff --git a/test/Templates.Test/template-baselines.json b/test/Templates.Test/template-baselines.json new file mode 100644 index 0000000000..48118c2e7d --- /dev/null +++ b/test/Templates.Test/template-baselines.json @@ -0,0 +1,868 @@ +{ + "razor": { + "Individual": { + "Template": "razor", + "Arguments": "new razor -au Individual", + "Files": [ + "app.db", + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Areas/Identity/Pages/_ViewStart.cshtml", + "Data/ApplicationDbContext.cs", + "Data/Migrations/00000000000000_CreateIdentitySchema.cs", + "Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs", + "Data/Migrations/ApplicationDbContextModelSnapshot.cs", + "Pages/About.cshtml", + "Pages/About.cshtml.cs", + "Pages/Contact.cshtml", + "Pages/Contact.cshtml.cs", + "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", + "Pages/Index.cshtml", + "Pages/Index.cshtml.cs", + "Pages/Privacy.cshtml", + "Pages/Privacy.cshtml.cs", + "Pages/_ViewImports.cshtml", + "Pages/_ViewStart.cshtml", + "Pages/Shared/_CookieConsentPartial.cshtml", + "Pages/Shared/_Layout.cshtml", + "Pages/Shared/_LoginPartial.cshtml", + "Pages/Shared/_ValidationScriptsPartial.cshtml", + "Properties/launchSettings.json", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "Individual" + }, + "Windows": { + "Template": "razor", + "Arguments": "new razor -au Windows", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Pages/About.cshtml", + "Pages/About.cshtml.cs", + "Pages/Contact.cshtml", + "Pages/Contact.cshtml.cs", + "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", + "Pages/Index.cshtml", + "Pages/Index.cshtml.cs", + "Pages/Privacy.cshtml", + "Pages/Privacy.cshtml.cs", + "Pages/_ViewImports.cshtml", + "Pages/_ViewStart.cshtml", + "Pages/Shared/_CookieConsentPartial.cshtml", + "Pages/Shared/_Layout.cshtml", + "Pages/Shared/_ValidationScriptsPartial.cshtml", + "Properties/launchSettings.json", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "Windows" + }, + "SingleOrg": { + "Template": "razor", + "Arguments": "new razor -au SingleOrg --aad-instance https://login.microsoftonline.com/ --domain fake-aad-domain.onmicrosoft.com --client-id db33c356-12cc-4953-9167-00ad56c2e8b2 --tenant-id 7e511586-66ec-4108-bc9c-a68dee0dc2aa", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Pages/About.cshtml", + "Pages/About.cshtml.cs", + "Pages/Contact.cshtml", + "Pages/Contact.cshtml.cs", + "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", + "Pages/Index.cshtml", + "Pages/Index.cshtml.cs", + "Pages/Privacy.cshtml", + "Pages/Privacy.cshtml.cs", + "Pages/_ViewImports.cshtml", + "Pages/_ViewStart.cshtml", + "Pages/Shared/_CookieConsentPartial.cshtml", + "Pages/Shared/_Layout.cshtml", + "Pages/Shared/_LoginPartial.cshtml", + "Pages/Shared/_ValidationScriptsPartial.cshtml", + "Properties/launchSettings.json", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "SingleOrg" + }, + "IndividualB2C": { + "Template": "razor", + "Arguments": "new razor -au IndividualB2C --aad-b2c-instance https://login.microsoftonline.com/tfp/ --domain fake-b2c-domain.onmicrosoft.com --client-id 64f31f76-2750-49e4-aab9-f5de105b5172 -ssp B2C_1_SiUpIn -rp B2C_1_SSPR -ep B2C_1_SiPe", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Pages/About.cshtml", + "Pages/About.cshtml.cs", + "Pages/Contact.cshtml", + "Pages/Contact.cshtml.cs", + "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", + "Pages/Index.cshtml", + "Pages/Index.cshtml.cs", + "Pages/Privacy.cshtml", + "Pages/Privacy.cshtml.cs", + "Pages/_ViewImports.cshtml", + "Pages/_ViewStart.cshtml", + "Pages/Shared/_CookieConsentPartial.cshtml", + "Pages/Shared/_Layout.cshtml", + "Pages/Shared/_LoginPartial.cshtml", + "Pages/Shared/_ValidationScriptsPartial.cshtml", + "Properties/launchSettings.json", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "IndividualB2C" + }, + "None": { + "Template": "razor", + "Arguments": "new razor -au None", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Pages/About.cshtml", + "Pages/About.cshtml.cs", + "Pages/Contact.cshtml", + "Pages/Contact.cshtml.cs", + "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", + "Pages/Index.cshtml", + "Pages/Index.cshtml.cs", + "Pages/Privacy.cshtml", + "Pages/Privacy.cshtml.cs", + "Pages/_ViewImports.cshtml", + "Pages/_ViewStart.cshtml", + "Pages/Shared/_CookieConsentPartial.cshtml", + "Pages/Shared/_Layout.cshtml", + "Pages/Shared/_ValidationScriptsPartial.cshtml", + "Properties/launchSettings.json", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "None" + }, + "MultiOrg": { + "Template": "razor", + "Arguments": "new razor -au MultiOrg --aad-instance https://login.microsoftonline.com/ --client-id bac81cbb-9fab-4a4e-9521-be07290c3a51", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Pages/About.cshtml", + "Pages/About.cshtml.cs", + "Pages/Contact.cshtml", + "Pages/Contact.cshtml.cs", + "Pages/Error.cshtml", + "Pages/Error.cshtml.cs", + "Pages/Index.cshtml", + "Pages/Index.cshtml.cs", + "Pages/Privacy.cshtml", + "Pages/Privacy.cshtml.cs", + "Pages/_ViewImports.cshtml", + "Pages/_ViewStart.cshtml", + "Pages/Shared/_CookieConsentPartial.cshtml", + "Pages/Shared/_Layout.cshtml", + "Pages/Shared/_LoginPartial.cshtml", + "Pages/Shared/_ValidationScriptsPartial.cshtml", + "Properties/launchSettings.json", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "MultiOrg" + } + }, + "webapi": { + "IndividualB2C": { + "Template": "webapi", + "Arguments": "new webapi -au IndividualB2C --aad-b2c-instance https://login.microsoftonline.com/tfp/ --domain fake-b2c-domain.onmicrosoft.com --client-id 64f31f76-2750-49e4-aab9-f5de105b5172 -ssp B2C_1_SiUpIn", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Controllers/ValuesController.cs", + "Properties/launchSettings.json" + ], + "AuthOption": "IndividualB2C" + }, + "SingleOrg": { + "Template": "webapi", + "Arguments": "new webapi -au SingleOrg --aad-instance https://login.microsoftonline.com/ --domain fake-aad-domain.onmicrosoft.com --client-id db33c356-12cc-4953-9167-00ad56c2e8b2 --tenant-id 7e511586-66ec-4108-bc9c-a68dee0dc2aa", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + + "Startup.cs", + "Controllers/ValuesController.cs", + "Properties/launchSettings.json" + ], + "AuthOption": "SingleOrg" + }, + "None": { + "Template": "webapi", + "Arguments": "new webapi -au None", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Controllers/ValuesController.cs", + "Properties/launchSettings.json" + ], + "AuthOption": "None" + }, + "Windows": { + "Template": "webapi", + "Arguments": "new webapi -au Windows", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + + "Controllers/ValuesController.cs", + "Properties/launchSettings.json" + ], + "AuthOption": "Windows" + } + }, + "mvc": { + "Individual": { + "Template": "mvc", + "Arguments": "new mvc -au Individual", + "Files": [ + "app.db", + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Areas/Identity/Pages/_ViewStart.cshtml", + "Controllers/HomeController.cs", + "Data/ApplicationDbContext.cs", + "Data/Migrations/00000000000000_CreateIdentitySchema.cs", + "Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs", + "Data/Migrations/ApplicationDbContextModelSnapshot.cs", + "Models/ErrorViewModel.cs", + "Properties/launchSettings.json", + "Views/_ViewImports.cshtml", + "Views/_ViewStart.cshtml", + "Views/Home/About.cshtml", + "Views/Home/Contact.cshtml", + "Views/Home/Index.cshtml", + "Views/Home/Privacy.cshtml", + "Views/Shared/Error.cshtml", + "Views/Shared/_CookieConsentPartial.cshtml", + "Views/Shared/_Layout.cshtml", + "Views/Shared/_LoginPartial.cshtml", + "Views/Shared/_ValidationScriptsPartial.cshtml", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/additional-methods.min.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.min.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "Individual" + }, + "Windows": { + "Template": "mvc", + "Arguments": "new mvc -au Windows", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Controllers/HomeController.cs", + "Models/ErrorViewModel.cs", + "Properties/launchSettings.json", + "Views/_ViewImports.cshtml", + "Views/_ViewStart.cshtml", + "Views/Home/About.cshtml", + "Views/Home/Contact.cshtml", + "Views/Home/Index.cshtml", + "Views/Home/Privacy.cshtml", + "Views/Shared/Error.cshtml", + "Views/Shared/_CookieConsentPartial.cshtml", + "Views/Shared/_Layout.cshtml", + "Views/Shared/_ValidationScriptsPartial.cshtml", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/additional-methods.min.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.min.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "Windows" + }, + "SingleOrg": { + "Template": "mvc", + "Arguments": "new mvc -au SingleOrg --aad-instance https://login.microsoftonline.com/ --domain fake-aad-domain.onmicrosoft.com --client-id db33c356-12cc-4953-9167-00ad56c2e8b2 --tenant-id 7e511586-66ec-4108-bc9c-a68dee0dc2aa", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Controllers/HomeController.cs", + "Models/ErrorViewModel.cs", + "Properties/launchSettings.json", + "Views/_ViewImports.cshtml", + "Views/_ViewStart.cshtml", + "Views/Home/About.cshtml", + "Views/Home/Contact.cshtml", + "Views/Home/Index.cshtml", + "Views/Home/Privacy.cshtml", + "Views/Shared/Error.cshtml", + "Views/Shared/_CookieConsentPartial.cshtml", + "Views/Shared/_Layout.cshtml", + "Views/Shared/_LoginPartial.cshtml", + "Views/Shared/_ValidationScriptsPartial.cshtml", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/additional-methods.min.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.min.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "SingleOrg" + }, + "IndividualB2C": { + "Template": "mvc", + "Arguments": "new mvc -au IndividualB2C --aad-b2c-instance https://login.microsoftonline.com/tfp/ --domain fake-b2c-domain.onmicrosoft.com --client-id 64f31f76-2750-49e4-aab9-f5de105b5172 -ssp B2C_1_SiUpIn -rp B2C_1_SSPR -ep B2C_1_SiPe", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Controllers/HomeController.cs", + "Models/ErrorViewModel.cs", + "Properties/launchSettings.json", + "Views/_ViewImports.cshtml", + "Views/_ViewStart.cshtml", + "Views/Home/About.cshtml", + "Views/Home/Contact.cshtml", + "Views/Home/Index.cshtml", + "Views/Home/Privacy.cshtml", + "Views/Shared/Error.cshtml", + "Views/Shared/_CookieConsentPartial.cshtml", + "Views/Shared/_Layout.cshtml", + "Views/Shared/_LoginPartial.cshtml", + "Views/Shared/_ValidationScriptsPartial.cshtml", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/additional-methods.min.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.min.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "IndividualB2C" + }, + "None": { + "Template": "mvc", + "Arguments": "new mvc -au None", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Controllers/HomeController.cs", + "Models/ErrorViewModel.cs", + "Properties/launchSettings.json", + "Views/_ViewImports.cshtml", + "Views/_ViewStart.cshtml", + "Views/Home/About.cshtml", + "Views/Home/Contact.cshtml", + "Views/Home/Index.cshtml", + "Views/Home/Privacy.cshtml", + "Views/Shared/Error.cshtml", + "Views/Shared/_CookieConsentPartial.cshtml", + "Views/Shared/_Layout.cshtml", + "Views/Shared/_ValidationScriptsPartial.cshtml", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/additional-methods.min.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.min.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "None" + }, + "MultiOrg": { + "Template": "mvc", + "Arguments": "new mvc -au MultiOrg --aad-instance https://login.microsoftonline.com/ --client-id bac81cbb-9fab-4a4e-9521-be07290c3a51", + "Files": [ + "appsettings.Development.json", + "appsettings.json", + "Program.cs", + "Startup.cs", + "Controllers/HomeController.cs", + "Models/ErrorViewModel.cs", + "Properties/launchSettings.json", + "Views/_ViewImports.cshtml", + "Views/_ViewStart.cshtml", + "Views/Home/About.cshtml", + "Views/Home/Contact.cshtml", + "Views/Home/Index.cshtml", + "Views/Home/Privacy.cshtml", + "Views/Shared/Error.cshtml", + "Views/Shared/_CookieConsentPartial.cshtml", + "Views/Shared/_Layout.cshtml", + "Views/Shared/_LoginPartial.cshtml", + "Views/Shared/_ValidationScriptsPartial.cshtml", + "wwwroot/favicon.ico", + "wwwroot/css/site.css", + "wwwroot/css/site.min.css", + "wwwroot/images/banner1.svg", + "wwwroot/images/banner2.svg", + "wwwroot/images/banner3.svg", + "wwwroot/images/banner4.svg", + "wwwroot/js/site.js", + "wwwroot/js/site.min.js", + "wwwroot/lib/bootstrap/.bower.json", + "wwwroot/lib/bootstrap/LICENSE", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap-theme.min.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.css.map", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css", + "wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.eot", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.svg", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.ttf", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff", + "wwwroot/lib/bootstrap/dist/fonts/glyphicons-halflings-regular.woff2", + "wwwroot/lib/bootstrap/dist/js/bootstrap.js", + "wwwroot/lib/bootstrap/dist/js/bootstrap.min.js", + "wwwroot/lib/bootstrap/dist/js/npm.js", + "wwwroot/lib/jquery/.bower.json", + "wwwroot/lib/jquery/LICENSE.txt", + "wwwroot/lib/jquery/dist/jquery.js", + "wwwroot/lib/jquery/dist/jquery.min.js", + "wwwroot/lib/jquery/dist/jquery.min.map", + "wwwroot/lib/jquery-validation/.bower.json", + "wwwroot/lib/jquery-validation/LICENSE.md", + "wwwroot/lib/jquery-validation/dist/additional-methods.js", + "wwwroot/lib/jquery-validation/dist/additional-methods.min.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.js", + "wwwroot/lib/jquery-validation/dist/jquery.validate.min.js", + "wwwroot/lib/jquery-validation-unobtrusive/.bower.json", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js", + "wwwroot/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js" + ], + "AuthOption": "MultiOrg" + } + } +}