From a80061f42be6ba7de36f8fea35086da58e08a69b Mon Sep 17 00:00:00 2001 From: Javier Calvarro Nelson Date: Wed, 11 Oct 2017 18:03:59 -0700 Subject: [PATCH] Move Identity to an Area for 2.1 --- .../.template.config/template.json | 21 +- .../Identity/Controllers/AccountController.cs | 465 ++++++++++++++++++ .../Identity}/Controllers/ManageController.cs | 11 +- .../Identity}/Data/ApplicationDbContext.cs | 4 +- ...000000000_CreateIdentitySchema.Designer.cs | 163 +++--- .../00000000000000_CreateIdentitySchema.cs | 16 +- .../ApplicationDbContextModelSnapshot.cs | 2 +- .../Extensions/EmailSenderExtensions.cs | 4 +- .../Extensions/UrlHelperExtensions.cs | 2 +- .../ExternalLoginViewModel.cs | 2 +- .../ForgotPasswordViewModel.cs | 2 +- .../AccountViewModels/LoginViewModel.cs | 2 +- .../LoginWith2faViewModel.cs | 2 +- .../LoginWithRecoveryCodeViewModel.cs | 2 +- .../AccountViewModels/RegisterViewModel.cs | 2 +- .../ResetPasswordViewModel.cs | 2 +- .../Identity}/Models/ApplicationUser.cs | 2 +- .../Areas/Identity/Models/ErrorViewModel.cs | 11 + .../ChangePasswordViewModel.cs | 2 +- .../EnableAuthenticatorViewModel.cs | 2 +- .../ExternalLoginsViewModel.cs | 2 +- .../GenerateRecoveryCodesViewModel.cs | 2 +- .../Models/ManageViewModels/IndexViewModel.cs | 2 +- .../ManageViewModels/RemoveLoginViewModel.cs | 2 +- .../ManageViewModels/SetPasswordViewModel.cs | 2 +- .../TwoFactorAuthenticationViewModel.cs | 2 +- .../Identity}/Services/EmailSender.cs | 2 +- .../Identity}/Services/IEmailSender.cs | 2 +- .../Views/Account/AccessDenied.cshtml | 8 + .../Views/Account/ConfirmEmail.cshtml | 0 .../Views/Account/ExternalLogin.cshtml | 0 .../Views/Account/ForgotPassword.cshtml | 0 .../Account/ForgotPasswordConfirmation.cshtml | 0 .../Identity}/Views/Account/Lockout.cshtml | 0 .../Identity}/Views/Account/Login.cshtml | 0 .../Views/Account/LoginWith2fa.cshtml | 0 .../Account/LoginWithRecoveryCode.cshtml | 0 .../Identity}/Views/Account/Register.cshtml | 0 .../Views/Account/ResetPassword.cshtml | 0 .../Account/ResetPasswordConfirmation.cshtml | 0 .../Identity/Views/Account/SignedOut.cshtml | 8 + .../Views/Manage/ChangePassword.cshtml | 0 .../Identity}/Views/Manage/Disable2fa.cshtml | 0 .../Views/Manage/EnableAuthenticator.cshtml | 0 .../Views/Manage/ExternalLogins.cshtml | 0 .../Views/Manage/GenerateRecoveryCodes.cshtml | 0 .../Identity}/Views/Manage/Index.cshtml | 0 .../Identity}/Views/Manage/ManageNavPages.cs | 0 .../Views/Manage/ResetAuthenticator.cshtml | 0 .../Identity}/Views/Manage/SetPassword.cshtml | 0 .../Manage/TwoFactorAuthentication.cshtml | 0 .../Identity}/Views/Manage/_Layout.cshtml | 0 .../Identity}/Views/Manage/_ManageNav.cshtml | 0 .../Views/Manage/_StatusMessage.cshtml | 0 .../Views/Manage/_ViewImports.cshtml | 0 .../Areas/Identity/Views/_ViewImports.cshtml | 6 + .../Areas/Identity/Views/_ViewStart.cshtml | 3 + .../Controllers/AccountController.cs | 443 ----------------- .../content/StarterWeb-CSharp/Startup.cs | 12 +- .../Views/Shared/_LoginPartial.cshtml | 10 +- .../Views/_ViewImports.cshtml | 9 +- test/Templates.Test/MvcTemplateTest.cs | 2 +- 62 files changed, 644 insertions(+), 592 deletions(-) create mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Controllers/AccountController.cs rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Controllers/ManageController.cs (98%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Data/ApplicationDbContext.cs (89%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs (87%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Data/Migrations/00000000000000_CreateIdentitySchema.cs (95%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Data/Migrations/ApplicationDbContextModelSnapshot.cs (99%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Extensions/EmailSenderExtensions.cs (83%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Extensions/UrlHelperExtensions.cs (94%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/AccountViewModels/ExternalLoginViewModel.cs (80%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/AccountViewModels/ForgotPasswordViewModel.cs (80%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/AccountViewModels/LoginViewModel.cs (87%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/AccountViewModels/LoginWith2faViewModel.cs (90%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/AccountViewModels/LoginWithRecoveryCodeViewModel.cs (84%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/AccountViewModels/RegisterViewModel.cs (92%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/AccountViewModels/ResetPasswordViewModel.cs (92%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/ApplicationUser.cs (85%) create mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ErrorViewModel.cs rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/ManageViewModels/ChangePasswordViewModel.cs (93%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/ManageViewModels/EnableAuthenticatorViewModel.cs (90%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/ManageViewModels/ExternalLoginsViewModel.cs (87%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/ManageViewModels/GenerateRecoveryCodesViewModel.cs (79%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/ManageViewModels/IndexViewModel.cs (88%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/ManageViewModels/RemoveLoginViewModel.cs (81%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/ManageViewModels/SetPasswordViewModel.cs (92%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Models/ManageViewModels/TwoFactorAuthenticationViewModel.cs (84%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Services/EmailSender.cs (90%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Services/IEmailSender.cs (81%) create mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/AccessDenied.cshtml rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Account/ConfirmEmail.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Account/ExternalLogin.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Account/ForgotPassword.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Account/ForgotPasswordConfirmation.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Account/Lockout.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Account/Login.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Account/LoginWith2fa.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Account/LoginWithRecoveryCode.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Account/Register.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Account/ResetPassword.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Account/ResetPasswordConfirmation.cshtml (100%) create mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/SignedOut.cshtml rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/ChangePassword.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/Disable2fa.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/EnableAuthenticator.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/ExternalLogins.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/GenerateRecoveryCodes.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/Index.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/ManageNavPages.cs (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/ResetAuthenticator.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/SetPassword.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/TwoFactorAuthentication.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/_Layout.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/_ManageNav.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/_StatusMessage.cshtml (100%) rename src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/{ => Areas/Identity}/Views/Manage/_ViewImports.cshtml (100%) create mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/_ViewImports.cshtml create mode 100644 src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/_ViewStart.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/.template.config/template.json b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/.template.config/template.json index d19241a192..3d6cb2c373 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/.template.config/template.json +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/.template.config/template.json @@ -38,26 +38,7 @@ { "condition": "(!IndividualLocalAuth)", "exclude": [ - "Controllers/ManageController.cs", - "Views/Account/ConfirmEmail.cshtml", - "Views/Account/ExternalLogin.cshtml", - "Views/Account/ForgotPassword.cshtml", - "Views/Account/ForgotPasswordConfirmation.cshtml", - "Views/Account/Lockout.cshtml", - "Views/Account/Login.cshtml", - "Views/Account/LoginWith2fa.cshtml", - "Views/Account/LoginWithRecoveryCode.cshtml", - "Views/Account/Register.cshtml", - "Views/Account/ResetPassword.cshtml", - "Views/Account/ResetPasswordConfirmation.cshtml", - "Views/Manage/**", - "Services/**", - "Data/**", - "Models/AccountViewModels/**", - "Models/ManageViewModels/**", - "Models/ApplicationUser.cs", - "Extensions/EmailSenderExtensions.cs", - "Extensions/UrlHelperExtensions.cs" + "Areas/Identity/**" ] }, { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Controllers/AccountController.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Controllers/AccountController.cs new file mode 100644 index 0000000000..02250ce380 --- /dev/null +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Controllers/AccountController.cs @@ -0,0 +1,465 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Claims; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.Rendering; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Company.WebApplication1.Controllers; +using Company.WebApplication1.Identity.Models; +using Company.WebApplication1.Identity.Models.AccountViewModels; +using Company.WebApplication1.Identity.Services; + +namespace Company.WebApplication1.Identity.Controllers +{ + [Authorize] + [Area("Identity")] + [Route("tfp/[area]/[controller]/[action]")] + public class AccountController : Controller + { + private readonly UserManager _userManager; + private readonly SignInManager _signInManager; + private readonly IEmailSender _emailSender; + private readonly ILogger _logger; + + public AccountController( + UserManager userManager, + SignInManager signInManager, + IEmailSender emailSender, + ILogger logger) + { + _userManager = userManager; + _signInManager = signInManager; + _emailSender = emailSender; + _logger = logger; + } + + [TempData] + public string ErrorMessage { get; set; } + + [HttpGet] + [AllowAnonymous] + public async Task Login(string returnUrl = null) + { + // Clear the existing external cookie to ensure a clean login process + await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); + + ViewData["ReturnUrl"] = returnUrl; + return View(); + } + + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task Login(LoginViewModel model, string returnUrl = null) + { + ViewData["ReturnUrl"] = returnUrl; + if (ModelState.IsValid) + { + // This doesn't count login failures towards account lockout + // To enable password failures to trigger account lockout, set lockoutOnFailure: true + var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false); + if (result.Succeeded) + { + _logger.LogInformation("User logged in."); + return RedirectToLocal(returnUrl); + } + if (result.RequiresTwoFactor) + { + return RedirectToAction(nameof(LoginWith2fa), new { returnUrl, model.RememberMe }); + } + if (result.IsLockedOut) + { + _logger.LogWarning("User account locked out."); + return RedirectToAction(nameof(Lockout)); + } + else + { + ModelState.AddModelError(string.Empty, "Invalid login attempt."); + return View(model); + } + } + + // If we got this far, something failed, redisplay form + return View(model); + } + + [HttpGet] + [AllowAnonymous] + public async Task LoginWith2fa(bool rememberMe, string returnUrl = null) + { + // Ensure the user has gone through the username & password screen first + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + + if (user == null) + { + throw new ApplicationException($"Unable to load two-factor authentication user."); + } + + var model = new LoginWith2faViewModel { RememberMe = rememberMe }; + ViewData["ReturnUrl"] = returnUrl; + + return View(model); + } + + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task LoginWith2fa(LoginWith2faViewModel model, bool rememberMe, string returnUrl = null) + { + if (!ModelState.IsValid) + { + return View(model); + } + + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) + { + throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); + } + + var authenticatorCode = model.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty); + + var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, model.RememberMachine); + + if (result.Succeeded) + { + _logger.LogInformation("User with ID {UserId} logged in with 2fa.", user.Id); + return RedirectToLocal(returnUrl); + } + else if (result.IsLockedOut) + { + _logger.LogWarning("User with ID {UserId} account locked out.", user.Id); + return RedirectToAction(nameof(Lockout)); + } + else + { + _logger.LogWarning("Invalid authenticator code entered for user with ID {UserId}.", user.Id); + ModelState.AddModelError(string.Empty, "Invalid authenticator code."); + return View(); + } + } + + [HttpGet] + [AllowAnonymous] + public async Task LoginWithRecoveryCode(string returnUrl = null) + { + // Ensure the user has gone through the username & password screen first + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) + { + throw new ApplicationException($"Unable to load two-factor authentication user."); + } + + ViewData["ReturnUrl"] = returnUrl; + + return View(); + } + + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task LoginWithRecoveryCode(LoginWithRecoveryCodeViewModel model, string returnUrl = null) + { + if (!ModelState.IsValid) + { + return View(model); + } + + var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); + if (user == null) + { + throw new ApplicationException($"Unable to load two-factor authentication user."); + } + + var recoveryCode = model.RecoveryCode.Replace(" ", string.Empty); + + var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode); + + if (result.Succeeded) + { + _logger.LogInformation("User with ID {UserId} logged in with a recovery code.", user.Id); + return RedirectToLocal(returnUrl); + } + if (result.IsLockedOut) + { + _logger.LogWarning("User with ID {UserId} account locked out.", user.Id); + return RedirectToAction(nameof(Lockout)); + } + else + { + _logger.LogWarning("Invalid recovery code entered for user with ID {UserId}", user.Id); + ModelState.AddModelError(string.Empty, "Invalid recovery code entered."); + return View(); + } + } + + [HttpGet] + [AllowAnonymous] + public IActionResult Lockout() + { + return View(); + } + + [HttpGet] + [AllowAnonymous] + public IActionResult Register(string returnUrl = null) + { + ViewData["ReturnUrl"] = returnUrl; + return View(); + } + + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task Register(RegisterViewModel model, string returnUrl = null) + { + ViewData["ReturnUrl"] = returnUrl; + if (ModelState.IsValid) + { + var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; + var result = await _userManager.CreateAsync(user, model.Password); + if (result.Succeeded) + { + _logger.LogInformation("User created a new account with password."); + + var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); + var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme); + await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl); + + await _signInManager.SignInAsync(user, isPersistent: false); + _logger.LogInformation("User created a new account with password."); + return RedirectToLocal(returnUrl); + } + AddErrors(result); + } + + // If we got this far, something failed, redisplay form + return View(model); + } + + [HttpPost] + [ValidateAntiForgeryToken] + public async Task Logout() + { + await _signInManager.SignOutAsync(); + _logger.LogInformation("User logged out."); + return RedirectToAction(nameof(HomeController.Index), "Home"); + } + + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public IActionResult ExternalLogin(string provider, string returnUrl = null) + { + // Request a redirect to the external login provider. + var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl }); + var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); + return Challenge(properties, provider); + } + + [HttpGet] + [AllowAnonymous] + public async Task ExternalLoginCallback(string returnUrl = null, string remoteError = null) + { + if (remoteError != null) + { + ErrorMessage = $"Error from external provider: {remoteError}"; + return RedirectToAction(nameof(Login)); + } + var info = await _signInManager.GetExternalLoginInfoAsync(); + if (info == null) + { + return RedirectToAction(nameof(Login)); + } + + // Sign in the user with this external login provider if the user already has a login. + var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true); + if (result.Succeeded) + { + _logger.LogInformation("User logged in with {Name} provider.", info.LoginProvider); + return RedirectToLocal(returnUrl); + } + if (result.IsLockedOut) + { + return RedirectToAction(nameof(Lockout)); + } + else + { + // If the user does not have an account, then ask the user to create an account. + ViewData["ReturnUrl"] = returnUrl; + ViewData["LoginProvider"] = info.LoginProvider; + var email = info.Principal.FindFirstValue(ClaimTypes.Email); + return View("ExternalLogin", new ExternalLoginViewModel { Email = email }); + } + } + + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task ExternalLoginConfirmation(ExternalLoginViewModel model, string returnUrl = null) + { + if (ModelState.IsValid) + { + // Get the information about the user from the external login provider + var info = await _signInManager.GetExternalLoginInfoAsync(); + if (info == null) + { + throw new ApplicationException("Error loading external login information during confirmation."); + } + var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; + var result = await _userManager.CreateAsync(user); + if (result.Succeeded) + { + result = await _userManager.AddLoginAsync(user, info); + if (result.Succeeded) + { + await _signInManager.SignInAsync(user, isPersistent: false); + _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider); + return RedirectToLocal(returnUrl); + } + } + AddErrors(result); + } + + ViewData["ReturnUrl"] = returnUrl; + return View(nameof(ExternalLogin), model); + } + + [HttpGet] + [AllowAnonymous] + public async Task ConfirmEmail(string userId, string code) + { + if (userId == null || code == null) + { + return RedirectToAction(nameof(HomeController.Index), "Home"); + } + var user = await _userManager.FindByIdAsync(userId); + if (user == null) + { + throw new ApplicationException($"Unable to load user with ID '{userId}'."); + } + var result = await _userManager.ConfirmEmailAsync(user, code); + return View(result.Succeeded ? "ConfirmEmail" : "Error"); + } + + [HttpGet] + [AllowAnonymous] + public IActionResult ForgotPassword() + { + return View(); + } + + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task ForgotPassword(ForgotPasswordViewModel model) + { + if (ModelState.IsValid) + { + var user = await _userManager.FindByEmailAsync(model.Email); + if (user == null || !(await _userManager.IsEmailConfirmedAsync(user))) + { + // Don't reveal that the user does not exist or is not confirmed + return RedirectToAction(nameof(ForgotPasswordConfirmation)); + } + + // For more information on how to enable account confirmation and password reset please + // visit https://go.microsoft.com/fwlink/?LinkID=532713 + var code = await _userManager.GeneratePasswordResetTokenAsync(user); + var callbackUrl = Url.ResetPasswordCallbackLink(user.Id, code, Request.Scheme); + await _emailSender.SendEmailAsync(model.Email, "Reset Password", + $"Please reset your password by clicking here: link"); + return RedirectToAction(nameof(ForgotPasswordConfirmation)); + } + + // If we got this far, something failed, redisplay form + return View(model); + } + + [HttpGet] + [AllowAnonymous] + public IActionResult ForgotPasswordConfirmation() + { + return View(); + } + + [HttpGet] + [AllowAnonymous] + public IActionResult ResetPassword(string code = null) + { + if (code == null) + { + throw new ApplicationException("A code must be supplied for password reset."); + } + var model = new ResetPasswordViewModel { Code = code }; + return View(model); + } + + [HttpPost] + [AllowAnonymous] + [ValidateAntiForgeryToken] + public async Task ResetPassword(ResetPasswordViewModel model) + { + if (!ModelState.IsValid) + { + return View(model); + } + var user = await _userManager.FindByEmailAsync(model.Email); + if (user == null) + { + // Don't reveal that the user does not exist + return RedirectToAction(nameof(ResetPasswordConfirmation)); + } + var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password); + if (result.Succeeded) + { + return RedirectToAction(nameof(ResetPasswordConfirmation)); + } + AddErrors(result); + return View(); + } + + [HttpGet] + [AllowAnonymous] + public IActionResult ResetPasswordConfirmation() + { + return View(); + } + + [HttpGet] + public IActionResult AccessDenied() + { + return View(); + } + + #region Helpers + + private void AddErrors(IdentityResult result) + { + foreach (var error in result.Errors) + { + ModelState.AddModelError(string.Empty, error.Description); + } + } + + private IActionResult RedirectToLocal(string returnUrl) + { + if (Url.IsLocalUrl(returnUrl)) + { + return Redirect(returnUrl); + } + else + { + return RedirectToAction(nameof(HomeController.Index), "Home"); + } + } + + #endregion + } +} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Controllers/ManageController.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Controllers/ManageController.cs similarity index 98% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Controllers/ManageController.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Controllers/ManageController.cs index d840959dd3..bacf0e2b6e 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Controllers/ManageController.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Controllers/ManageController.cs @@ -10,14 +10,15 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Company.WebApplication1.Models; -using Company.WebApplication1.Models.ManageViewModels; -using Company.WebApplication1.Services; +using Company.WebApplication1.Identity.Models; +using Company.WebApplication1.Identity.Models.ManageViewModels; +using Company.WebApplication1.Identity.Services; -namespace Company.WebApplication1.Controllers +namespace Company.WebApplication1.Identity.Controllers { [Authorize] - [Route("[controller]/[action]")] + [Area("Identity")] + [Route("tfp/[area]/[controller]/[action]")] public class ManageController : Controller { private readonly UserManager _userManager; diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/ApplicationDbContext.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/ApplicationDbContext.cs similarity index 89% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/ApplicationDbContext.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/ApplicationDbContext.cs index 32da6ff1d1..6467854d60 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/ApplicationDbContext.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/ApplicationDbContext.cs @@ -4,9 +4,9 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; -using Company.WebApplication1.Models; +using Company.WebApplication1.Identity.Models; -namespace Company.WebApplication1.Data +namespace Company.WebApplication1.Identity.Data { public class ApplicationDbContext : IdentityDbContext { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs similarity index 87% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs index 483520ed85..9121b7f8bd 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/Migrations/00000000000000_CreateIdentitySchema.Designer.cs @@ -9,7 +9,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; -namespace Company.WebApplication1.Data.Migrations +namespace Company.WebApplication1.Identity.Data.Migrations { [DbContext(typeof(ApplicationDbContext))] [Migration("00000000000000_CreateIdentitySchema")] @@ -17,17 +17,85 @@ namespace Company.WebApplication1.Data.Migrations { protected override void BuildTargetModel(ModelBuilder modelBuilder) { +#pragma warning disable 612, 618 modelBuilder #if (UseLocalDB) - .HasAnnotation("ProductVersion", "1.0.0-rc3") + .HasAnnotation("ProductVersion", "2.0.0-rtm-26452") .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn); #else - .HasAnnotation("ProductVersion", "1.0.2"); + .HasAnnotation("ProductVersion", "2.0.0-rtm-26452"); #endif + modelBuilder.Entity("Company.WebApplication1.Models.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd(); + + b.Property("AccessFailedCount"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken(); + + b.Property("Email") +#if (UseLocalDB) + .HasAnnotation("MaxLength", 256); +#else + .HasMaxLength(256); +#endif + + b.Property("EmailConfirmed"); + + b.Property("LockoutEnabled"); + + b.Property("LockoutEnd"); + + b.Property("NormalizedEmail") +#if (UseLocalDB) + .HasAnnotation("MaxLength", 256); +#else + .HasMaxLength(256); +#endif + + b.Property("NormalizedUserName") +#if (UseLocalDB) + .HasAnnotation("MaxLength", 256); +#else + .HasMaxLength(256); +#endif + + b.Property("PasswordHash"); + + b.Property("PhoneNumber"); + + b.Property("PhoneNumberConfirmed"); + + b.Property("SecurityStamp"); + + b.Property("TwoFactorEnabled"); + + b.Property("UserName") +#if (UseLocalDB) + .HasAnnotation("MaxLength", 256); +#else + .HasMaxLength(256); +#endif + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasName("UserNameIndex"); + + b.ToTable("AspNetUsers"); + }); + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRole", b => { - b.Property("Id"); + b.Property("Id") + .ValueGeneratedOnAdd(); b.Property("ConcurrencyStamp") .IsConcurrencyToken(); @@ -49,6 +117,7 @@ namespace Company.WebApplication1.Data.Migrations b.HasKey("Id"); b.HasIndex("NormalizedName") + .IsUnique() .HasName("RoleNameIndex"); b.ToTable("AspNetRoles"); @@ -120,8 +189,6 @@ namespace Company.WebApplication1.Data.Migrations b.HasIndex("RoleId"); - b.HasIndex("UserId"); - b.ToTable("AspNetUserRoles"); }); @@ -140,75 +207,10 @@ namespace Company.WebApplication1.Data.Migrations b.ToTable("AspNetUserTokens"); }); - modelBuilder.Entity("Company.WebApplication1.Models.ApplicationUser", b => - { - b.Property("Id"); - - b.Property("AccessFailedCount"); - - b.Property("ConcurrencyStamp") - .IsConcurrencyToken(); - - b.Property("Email") -#if (UseLocalDB) - .HasAnnotation("MaxLength", 256); -#else - .HasMaxLength(256); -#endif - - b.Property("EmailConfirmed"); - - b.Property("LockoutEnabled"); - - b.Property("LockoutEnd"); - - b.Property("NormalizedEmail") -#if (UseLocalDB) - .HasAnnotation("MaxLength", 256); -#else - .HasMaxLength(256); -#endif - - b.Property("NormalizedUserName") -#if (UseLocalDB) - .HasAnnotation("MaxLength", 256); -#else - .HasMaxLength(256); -#endif - - b.Property("PasswordHash"); - - b.Property("PhoneNumber"); - - b.Property("PhoneNumberConfirmed"); - - b.Property("SecurityStamp"); - - b.Property("TwoFactorEnabled"); - - b.Property("UserName") -#if (UseLocalDB) - .HasAnnotation("MaxLength", 256); -#else - .HasMaxLength(256); -#endif - - b.HasKey("Id"); - - b.HasIndex("NormalizedEmail") - .HasName("EmailIndex"); - - b.HasIndex("NormalizedUserName") - .IsUnique() - .HasName("UserNameIndex"); - - b.ToTable("AspNetUsers"); - }); - modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") - .WithMany("Claims") + .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade); }); @@ -216,7 +218,7 @@ namespace Company.WebApplication1.Data.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => { b.HasOne("Company.WebApplication1.Models.ApplicationUser") - .WithMany("Claims") + .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade); }); @@ -224,7 +226,7 @@ namespace Company.WebApplication1.Data.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => { b.HasOne("Company.WebApplication1.Models.ApplicationUser") - .WithMany("Logins") + .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade); }); @@ -232,15 +234,24 @@ namespace Company.WebApplication1.Data.Migrations modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => { b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole") - .WithMany("Users") + .WithMany() .HasForeignKey("RoleId") .OnDelete(DeleteBehavior.Cascade); b.HasOne("Company.WebApplication1.Models.ApplicationUser") - .WithMany("Roles") + .WithMany() .HasForeignKey("UserId") .OnDelete(DeleteBehavior.Cascade); }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("Company.WebApplication1.Models.ApplicationUser") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade); + }); +#pragma warning restore 612, 618 } } } diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/Migrations/00000000000000_CreateIdentitySchema.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/Migrations/00000000000000_CreateIdentitySchema.cs similarity index 95% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/Migrations/00000000000000_CreateIdentitySchema.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/Migrations/00000000000000_CreateIdentitySchema.cs index 93771c4379..5bfd1e7875 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/Migrations/00000000000000_CreateIdentitySchema.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/Migrations/00000000000000_CreateIdentitySchema.cs @@ -7,7 +7,7 @@ using Microsoft.EntityFrameworkCore.Metadata; #endif using Microsoft.EntityFrameworkCore.Migrations; -namespace Company.WebApplication1.Data.Migrations +namespace Company.WebApplication1.Identity.Data.Migrations { public partial class CreateIdentitySchema : Migration { @@ -39,6 +39,12 @@ namespace Company.WebApplication1.Data.Migrations constraints: table => { table.PrimaryKey("PK_AspNetUserTokens", x => new { x.UserId, x.LoginProvider, x.Name }); + table.ForeignKey( + name: "FK_AspNetUserTokens_AspNetUsers_UserId", + column: x => x.UserId, + principalTable: "AspNetUsers", + principalColumn: "Id", + onDelete: ReferentialAction.Cascade); }); migrationBuilder.CreateTable( @@ -163,7 +169,8 @@ namespace Company.WebApplication1.Data.Migrations migrationBuilder.CreateIndex( name: "RoleNameIndex", table: "AspNetRoles", - column: "NormalizedName"); + column: "NormalizedName", + unique: true); migrationBuilder.CreateIndex( name: "IX_AspNetRoleClaims_RoleId", @@ -185,11 +192,6 @@ namespace Company.WebApplication1.Data.Migrations table: "AspNetUserRoles", column: "RoleId"); - migrationBuilder.CreateIndex( - name: "IX_AspNetUserRoles_UserId", - table: "AspNetUserRoles", - column: "UserId"); - migrationBuilder.CreateIndex( name: "EmailIndex", table: "AspNetUsers", diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/Migrations/ApplicationDbContextModelSnapshot.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/Migrations/ApplicationDbContextModelSnapshot.cs similarity index 99% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/Migrations/ApplicationDbContextModelSnapshot.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/Migrations/ApplicationDbContextModelSnapshot.cs index 01138f20da..1a83a578c9 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Data/Migrations/ApplicationDbContextModelSnapshot.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Data/Migrations/ApplicationDbContextModelSnapshot.cs @@ -9,7 +9,7 @@ using Microsoft.EntityFrameworkCore.Infrastructure; using Microsoft.EntityFrameworkCore.Metadata; using Microsoft.EntityFrameworkCore.Migrations; -namespace Company.WebApplication1.Data.Migrations +namespace Company.WebApplication1.Identity.Data.Migrations { [DbContext(typeof(ApplicationDbContext))] partial class ApplicationDbContextModelSnapshot : ModelSnapshot diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Extensions/EmailSenderExtensions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Extensions/EmailSenderExtensions.cs similarity index 83% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Extensions/EmailSenderExtensions.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Extensions/EmailSenderExtensions.cs index 6db948bc3a..df2e9877d4 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Extensions/EmailSenderExtensions.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Extensions/EmailSenderExtensions.cs @@ -3,9 +3,9 @@ using System.Collections.Generic; using System.Linq; using System.Text.Encodings.Web; using System.Threading.Tasks; -using Company.WebApplication1.Services; +using Company.WebApplication1.Identity.Services; -namespace Company.WebApplication1.Services +namespace Company.WebApplication1.Identity.Services { public static class EmailSenderExtensions { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Extensions/UrlHelperExtensions.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Extensions/UrlHelperExtensions.cs similarity index 94% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Extensions/UrlHelperExtensions.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Extensions/UrlHelperExtensions.cs index 6d1c3f6fce..c9defed45b 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Extensions/UrlHelperExtensions.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Extensions/UrlHelperExtensions.cs @@ -2,7 +2,7 @@ using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -using Company.WebApplication1.Controllers; +using Company.WebApplication1.Identity.Controllers; namespace Microsoft.AspNetCore.Mvc { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/ExternalLoginViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/ExternalLoginViewModel.cs similarity index 80% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/ExternalLoginViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/ExternalLoginViewModel.cs index 66167fd25e..058198baab 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/ExternalLoginViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/ExternalLoginViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.AccountViewModels +namespace Company.WebApplication1.Identity.Models.AccountViewModels { public class ExternalLoginViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/ForgotPasswordViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/ForgotPasswordViewModel.cs similarity index 80% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/ForgotPasswordViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/ForgotPasswordViewModel.cs index dc6cddb9a8..491c7efb7d 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/ForgotPasswordViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/ForgotPasswordViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.AccountViewModels +namespace Company.WebApplication1.Identity.Models.AccountViewModels { public class ForgotPasswordViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/LoginViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/LoginViewModel.cs similarity index 87% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/LoginViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/LoginViewModel.cs index d502be1bff..6bd7021825 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/LoginViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/LoginViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.AccountViewModels +namespace Company.WebApplication1.Identity.Models.AccountViewModels { public class LoginViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/LoginWith2faViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/LoginWith2faViewModel.cs similarity index 90% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/LoginWith2faViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/LoginWith2faViewModel.cs index 2f91ce39d4..63cafb4937 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/LoginWith2faViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/LoginWith2faViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.AccountViewModels +namespace Company.WebApplication1.Identity.Models.AccountViewModels { public class LoginWith2faViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/LoginWithRecoveryCodeViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/LoginWithRecoveryCodeViewModel.cs similarity index 84% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/LoginWithRecoveryCodeViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/LoginWithRecoveryCodeViewModel.cs index f2cc20de1d..a68eb41923 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/LoginWithRecoveryCodeViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/LoginWithRecoveryCodeViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.AccountViewModels +namespace Company.WebApplication1.Identity.Models.AccountViewModels { public class LoginWithRecoveryCodeViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/RegisterViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/RegisterViewModel.cs similarity index 92% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/RegisterViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/RegisterViewModel.cs index 76dbe7234c..5b088c6b41 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/RegisterViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/RegisterViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.AccountViewModels +namespace Company.WebApplication1.Identity.Models.AccountViewModels { public class RegisterViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/ResetPasswordViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/ResetPasswordViewModel.cs similarity index 92% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/ResetPasswordViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/ResetPasswordViewModel.cs index 10f4dcc474..70db8603cc 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/AccountViewModels/ResetPasswordViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/AccountViewModels/ResetPasswordViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.AccountViewModels +namespace Company.WebApplication1.Identity.Models.AccountViewModels { public class ResetPasswordViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ApplicationUser.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ApplicationUser.cs similarity index 85% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ApplicationUser.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ApplicationUser.cs index f4fcc44b85..f6a8f2aed2 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ApplicationUser.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ApplicationUser.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Identity; -namespace Company.WebApplication1.Models +namespace Company.WebApplication1.Identity.Models { // Add profile data for application users by adding properties to the ApplicationUser class public class ApplicationUser : IdentityUser diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ErrorViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ErrorViewModel.cs new file mode 100644 index 0000000000..cd1832cadc --- /dev/null +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ErrorViewModel.cs @@ -0,0 +1,11 @@ +using System; + +namespace Company.WebApplication1.Identity.Models +{ + public class ErrorViewModel + { + public string RequestId { get; set; } + + public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); + } +} \ No newline at end of file diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/ChangePasswordViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/ChangePasswordViewModel.cs similarity index 93% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/ChangePasswordViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/ChangePasswordViewModel.cs index 710132efed..0350e6be00 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/ChangePasswordViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/ChangePasswordViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.ManageViewModels +namespace Company.WebApplication1.Identity.Models.ManageViewModels { public class ChangePasswordViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/EnableAuthenticatorViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/EnableAuthenticatorViewModel.cs similarity index 90% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/EnableAuthenticatorViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/EnableAuthenticatorViewModel.cs index 3f3323f216..c652c923c7 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/EnableAuthenticatorViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/EnableAuthenticatorViewModel.cs @@ -5,7 +5,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.ManageViewModels +namespace Company.WebApplication1.Identity.Models.ManageViewModels { public class EnableAuthenticatorViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/ExternalLoginsViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/ExternalLoginsViewModel.cs similarity index 87% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/ExternalLoginsViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/ExternalLoginsViewModel.cs index 0675aa0870..fdd7d1b98b 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/ExternalLoginsViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/ExternalLoginsViewModel.cs @@ -5,7 +5,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Identity; -namespace Company.WebApplication1.Models.ManageViewModels +namespace Company.WebApplication1.Identity.Models.ManageViewModels { public class ExternalLoginsViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/GenerateRecoveryCodesViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/GenerateRecoveryCodesViewModel.cs similarity index 79% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/GenerateRecoveryCodesViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/GenerateRecoveryCodesViewModel.cs index 05f1fe8a70..53226778df 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/GenerateRecoveryCodesViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/GenerateRecoveryCodesViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.ManageViewModels +namespace Company.WebApplication1.Identity.Models.ManageViewModels { public class GenerateRecoveryCodesViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/IndexViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/IndexViewModel.cs similarity index 88% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/IndexViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/IndexViewModel.cs index 1a5fe12d17..b7a383111f 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/IndexViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/IndexViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.ManageViewModels +namespace Company.WebApplication1.Identity.Models.ManageViewModels { public class IndexViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/RemoveLoginViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/RemoveLoginViewModel.cs similarity index 81% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/RemoveLoginViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/RemoveLoginViewModel.cs index 998a5bb122..04ce0cf1f7 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/RemoveLoginViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/RemoveLoginViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.ManageViewModels +namespace Company.WebApplication1.Identity.Models.ManageViewModels { public class RemoveLoginViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/SetPasswordViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/SetPasswordViewModel.cs similarity index 92% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/SetPasswordViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/SetPasswordViewModel.cs index 6fcfe3ec9d..e726000815 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/SetPasswordViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/SetPasswordViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.ManageViewModels +namespace Company.WebApplication1.Identity.Models.ManageViewModels { public class SetPasswordViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/TwoFactorAuthenticationViewModel.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/TwoFactorAuthenticationViewModel.cs similarity index 84% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/TwoFactorAuthenticationViewModel.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/TwoFactorAuthenticationViewModel.cs index b7847aff86..758335b455 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Models/ManageViewModels/TwoFactorAuthenticationViewModel.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Models/ManageViewModels/TwoFactorAuthenticationViewModel.cs @@ -4,7 +4,7 @@ using System.ComponentModel.DataAnnotations; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Models.ManageViewModels +namespace Company.WebApplication1.Identity.Models.ManageViewModels { public class TwoFactorAuthenticationViewModel { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Services/EmailSender.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Services/EmailSender.cs similarity index 90% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Services/EmailSender.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Services/EmailSender.cs index 2521999578..ca332632f8 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Services/EmailSender.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Services/EmailSender.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Services +namespace Company.WebApplication1.Identity.Services { // This class is used by the application to send email for account confirmation and password reset. // For more details see https://go.microsoft.com/fwlink/?LinkID=532713 diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Services/IEmailSender.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Services/IEmailSender.cs similarity index 81% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Services/IEmailSender.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Services/IEmailSender.cs index ce6e1e9e84..c721894626 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Services/IEmailSender.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Services/IEmailSender.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; -namespace Company.WebApplication1.Services +namespace Company.WebApplication1.Identity.Services { public interface IEmailSender { diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/AccessDenied.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/AccessDenied.cshtml new file mode 100644 index 0000000000..3a5a00852c --- /dev/null +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/AccessDenied.cshtml @@ -0,0 +1,8 @@ +@{ + ViewData["Title"] = "Access denied"; +} + +
+

ViewData["Title"]

+

You do not have access to this resource.

+
diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ConfirmEmail.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ConfirmEmail.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ConfirmEmail.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ConfirmEmail.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ExternalLogin.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ExternalLogin.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ExternalLogin.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ExternalLogin.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ForgotPassword.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ForgotPassword.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ForgotPassword.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ForgotPassword.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ForgotPasswordConfirmation.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ForgotPasswordConfirmation.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ForgotPasswordConfirmation.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ForgotPasswordConfirmation.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/Lockout.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/Lockout.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/Lockout.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/Lockout.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/Login.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/Login.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/Login.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/Login.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/LoginWith2fa.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/LoginWith2fa.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/LoginWith2fa.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/LoginWith2fa.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/LoginWithRecoveryCode.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/LoginWithRecoveryCode.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/LoginWithRecoveryCode.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/LoginWithRecoveryCode.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/Register.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/Register.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/Register.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/Register.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ResetPassword.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ResetPassword.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ResetPassword.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ResetPassword.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ResetPasswordConfirmation.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ResetPasswordConfirmation.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Account/ResetPasswordConfirmation.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/ResetPasswordConfirmation.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/SignedOut.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/SignedOut.cshtml new file mode 100644 index 0000000000..c7fb988cd4 --- /dev/null +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Account/SignedOut.cshtml @@ -0,0 +1,8 @@ +@{ + ViewData["Title"] = "Signed out"; +} + +

@ViewData["Title"]

+

+ You have successfully signed out. +

diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/ChangePassword.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/ChangePassword.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/ChangePassword.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/ChangePassword.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/Disable2fa.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/Disable2fa.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/Disable2fa.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/Disable2fa.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/EnableAuthenticator.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/EnableAuthenticator.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/EnableAuthenticator.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/EnableAuthenticator.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/ExternalLogins.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/ExternalLogins.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/ExternalLogins.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/ExternalLogins.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/GenerateRecoveryCodes.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/GenerateRecoveryCodes.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/GenerateRecoveryCodes.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/GenerateRecoveryCodes.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/Index.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/Index.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/Index.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/Index.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/ManageNavPages.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/ManageNavPages.cs similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/ManageNavPages.cs rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/ManageNavPages.cs diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/ResetAuthenticator.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/ResetAuthenticator.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/ResetAuthenticator.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/ResetAuthenticator.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/SetPassword.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/SetPassword.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/SetPassword.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/SetPassword.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/TwoFactorAuthentication.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/TwoFactorAuthentication.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/TwoFactorAuthentication.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/TwoFactorAuthentication.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/_Layout.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/_Layout.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/_Layout.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/_Layout.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/_ManageNav.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/_ManageNav.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/_ManageNav.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/_ManageNav.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/_StatusMessage.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/_StatusMessage.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/_StatusMessage.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/_StatusMessage.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/_ViewImports.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/_ViewImports.cshtml similarity index 100% rename from src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Manage/_ViewImports.cshtml rename to src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/Manage/_ViewImports.cshtml diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/_ViewImports.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/_ViewImports.cshtml new file mode 100644 index 0000000000..64c727d524 --- /dev/null +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/_ViewImports.cshtml @@ -0,0 +1,6 @@ +@using Microsoft.AspNetCore.Identity +@using Company.WebApplication1.Identity +@using Company.WebApplication1.Identity.Models +@using Company.WebApplication1.Identity.Models.AccountViewModels +@using Company.WebApplication1.Identity.Models.ManageViewModels +@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers \ No newline at end of file diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/_ViewStart.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/_ViewStart.cshtml new file mode 100644 index 0000000000..a5f10045db --- /dev/null +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Areas/Identity/Views/_ViewStart.cshtml @@ -0,0 +1,3 @@ +@{ + Layout = "_Layout"; +} diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Controllers/AccountController.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Controllers/AccountController.cs index fdef1e3a48..6dbfc5a4c6 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Controllers/AccountController.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Controllers/AccountController.cs @@ -15,9 +15,6 @@ using Microsoft.AspNetCore.Authentication.OpenIdConnect; #if (IndividualAuth) using Microsoft.AspNetCore.Authorization; #endif -#if (IndividualLocalAuth) -using Microsoft.AspNetCore.Identity; -#endif using Microsoft.AspNetCore.Mvc; #if (IndividualAuth) using Microsoft.AspNetCore.Mvc.Rendering; @@ -26,8 +23,6 @@ using Microsoft.Extensions.Options; #endif #if (IndividualLocalAuth) using Company.WebApplication1.Models; -using Company.WebApplication1.Models.AccountViewModels; -using Company.WebApplication1.Services; #endif namespace Company.WebApplication1.Controllers @@ -70,418 +65,6 @@ namespace Company.WebApplication1.Controllers return View(); } #endif -#if (IndividualLocalAuth) - private readonly UserManager _userManager; - private readonly SignInManager _signInManager; - private readonly IEmailSender _emailSender; - private readonly ILogger _logger; - - public AccountController( - UserManager userManager, - SignInManager signInManager, - IEmailSender emailSender, - ILogger logger) - { - _userManager = userManager; - _signInManager = signInManager; - _emailSender = emailSender; - _logger = logger; - } - - [TempData] - public string ErrorMessage { get; set; } - - [HttpGet] - [AllowAnonymous] - public async Task Login(string returnUrl = null) - { - // Clear the existing external cookie to ensure a clean login process - await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme); - - ViewData["ReturnUrl"] = returnUrl; - return View(); - } - - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task Login(LoginViewModel model, string returnUrl = null) - { - ViewData["ReturnUrl"] = returnUrl; - if (ModelState.IsValid) - { - // This doesn't count login failures towards account lockout - // To enable password failures to trigger account lockout, set lockoutOnFailure: true - var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false); - if (result.Succeeded) - { - _logger.LogInformation("User logged in."); - return RedirectToLocal(returnUrl); - } - if (result.RequiresTwoFactor) - { - return RedirectToAction(nameof(LoginWith2fa), new { returnUrl, model.RememberMe }); - } - if (result.IsLockedOut) - { - _logger.LogWarning("User account locked out."); - return RedirectToAction(nameof(Lockout)); - } - else - { - ModelState.AddModelError(string.Empty, "Invalid login attempt."); - return View(model); - } - } - - // If we got this far, something failed, redisplay form - return View(model); - } - - [HttpGet] - [AllowAnonymous] - public async Task LoginWith2fa(bool rememberMe, string returnUrl = null) - { - // Ensure the user has gone through the username & password screen first - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - - if (user == null) - { - throw new ApplicationException($"Unable to load two-factor authentication user."); - } - - var model = new LoginWith2faViewModel { RememberMe = rememberMe }; - ViewData["ReturnUrl"] = returnUrl; - - return View(model); - } - - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task LoginWith2fa(LoginWith2faViewModel model, bool rememberMe, string returnUrl = null) - { - if (!ModelState.IsValid) - { - return View(model); - } - - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) - { - throw new ApplicationException($"Unable to load user with ID '{_userManager.GetUserId(User)}'."); - } - - var authenticatorCode = model.TwoFactorCode.Replace(" ", string.Empty).Replace("-", string.Empty); - - var result = await _signInManager.TwoFactorAuthenticatorSignInAsync(authenticatorCode, rememberMe, model.RememberMachine); - - if (result.Succeeded) - { - _logger.LogInformation("User with ID {UserId} logged in with 2fa.", user.Id); - return RedirectToLocal(returnUrl); - } - else if (result.IsLockedOut) - { - _logger.LogWarning("User with ID {UserId} account locked out.", user.Id); - return RedirectToAction(nameof(Lockout)); - } - else - { - _logger.LogWarning("Invalid authenticator code entered for user with ID {UserId}.", user.Id); - ModelState.AddModelError(string.Empty, "Invalid authenticator code."); - return View(); - } - } - - [HttpGet] - [AllowAnonymous] - public async Task LoginWithRecoveryCode(string returnUrl = null) - { - // Ensure the user has gone through the username & password screen first - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) - { - throw new ApplicationException($"Unable to load two-factor authentication user."); - } - - ViewData["ReturnUrl"] = returnUrl; - - return View(); - } - - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task LoginWithRecoveryCode(LoginWithRecoveryCodeViewModel model, string returnUrl = null) - { - if (!ModelState.IsValid) - { - return View(model); - } - - var user = await _signInManager.GetTwoFactorAuthenticationUserAsync(); - if (user == null) - { - throw new ApplicationException($"Unable to load two-factor authentication user."); - } - - var recoveryCode = model.RecoveryCode.Replace(" ", string.Empty); - - var result = await _signInManager.TwoFactorRecoveryCodeSignInAsync(recoveryCode); - - if (result.Succeeded) - { - _logger.LogInformation("User with ID {UserId} logged in with a recovery code.", user.Id); - return RedirectToLocal(returnUrl); - } - if (result.IsLockedOut) - { - _logger.LogWarning("User with ID {UserId} account locked out.", user.Id); - return RedirectToAction(nameof(Lockout)); - } - else - { - _logger.LogWarning("Invalid recovery code entered for user with ID {UserId}", user.Id); - ModelState.AddModelError(string.Empty, "Invalid recovery code entered."); - return View(); - } - } - - [HttpGet] - [AllowAnonymous] - public IActionResult Lockout() - { - return View(); - } - - [HttpGet] - [AllowAnonymous] - public IActionResult Register(string returnUrl = null) - { - ViewData["ReturnUrl"] = returnUrl; - return View(); - } - - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task Register(RegisterViewModel model, string returnUrl = null) - { - ViewData["ReturnUrl"] = returnUrl; - if (ModelState.IsValid) - { - var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; - var result = await _userManager.CreateAsync(user, model.Password); - if (result.Succeeded) - { - _logger.LogInformation("User created a new account with password."); - - var code = await _userManager.GenerateEmailConfirmationTokenAsync(user); - var callbackUrl = Url.EmailConfirmationLink(user.Id, code, Request.Scheme); - await _emailSender.SendEmailConfirmationAsync(model.Email, callbackUrl); - - await _signInManager.SignInAsync(user, isPersistent: false); - _logger.LogInformation("User created a new account with password."); - return RedirectToLocal(returnUrl); - } - AddErrors(result); - } - - // If we got this far, something failed, redisplay form - return View(model); - } - - [HttpPost] - [ValidateAntiForgeryToken] - public async Task Logout() - { - await _signInManager.SignOutAsync(); - _logger.LogInformation("User logged out."); - return RedirectToAction(nameof(HomeController.Index), "Home"); - } - - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public IActionResult ExternalLogin(string provider, string returnUrl = null) - { - // Request a redirect to the external login provider. - var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { returnUrl }); - var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); - return Challenge(properties, provider); - } - - [HttpGet] - [AllowAnonymous] - public async Task ExternalLoginCallback(string returnUrl = null, string remoteError = null) - { - if (remoteError != null) - { - ErrorMessage = $"Error from external provider: {remoteError}"; - return RedirectToAction(nameof(Login)); - } - var info = await _signInManager.GetExternalLoginInfoAsync(); - if (info == null) - { - return RedirectToAction(nameof(Login)); - } - - // Sign in the user with this external login provider if the user already has a login. - var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false, bypassTwoFactor: true); - if (result.Succeeded) - { - _logger.LogInformation("User logged in with {Name} provider.", info.LoginProvider); - return RedirectToLocal(returnUrl); - } - if (result.IsLockedOut) - { - return RedirectToAction(nameof(Lockout)); - } - else - { - // If the user does not have an account, then ask the user to create an account. - ViewData["ReturnUrl"] = returnUrl; - ViewData["LoginProvider"] = info.LoginProvider; - var email = info.Principal.FindFirstValue(ClaimTypes.Email); - return View("ExternalLogin", new ExternalLoginViewModel { Email = email }); - } - } - - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task ExternalLoginConfirmation(ExternalLoginViewModel model, string returnUrl = null) - { - if (ModelState.IsValid) - { - // Get the information about the user from the external login provider - var info = await _signInManager.GetExternalLoginInfoAsync(); - if (info == null) - { - throw new ApplicationException("Error loading external login information during confirmation."); - } - var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; - var result = await _userManager.CreateAsync(user); - if (result.Succeeded) - { - result = await _userManager.AddLoginAsync(user, info); - if (result.Succeeded) - { - await _signInManager.SignInAsync(user, isPersistent: false); - _logger.LogInformation("User created an account using {Name} provider.", info.LoginProvider); - return RedirectToLocal(returnUrl); - } - } - AddErrors(result); - } - - ViewData["ReturnUrl"] = returnUrl; - return View(nameof(ExternalLogin), model); - } - - [HttpGet] - [AllowAnonymous] - public async Task ConfirmEmail(string userId, string code) - { - if (userId == null || code == null) - { - return RedirectToAction(nameof(HomeController.Index), "Home"); - } - var user = await _userManager.FindByIdAsync(userId); - if (user == null) - { - throw new ApplicationException($"Unable to load user with ID '{userId}'."); - } - var result = await _userManager.ConfirmEmailAsync(user, code); - return View(result.Succeeded ? "ConfirmEmail" : "Error"); - } - - [HttpGet] - [AllowAnonymous] - public IActionResult ForgotPassword() - { - return View(); - } - - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task ForgotPassword(ForgotPasswordViewModel model) - { - if (ModelState.IsValid) - { - var user = await _userManager.FindByEmailAsync(model.Email); - if (user == null || !(await _userManager.IsEmailConfirmedAsync(user))) - { - // Don't reveal that the user does not exist or is not confirmed - return RedirectToAction(nameof(ForgotPasswordConfirmation)); - } - - // For more information on how to enable account confirmation and password reset please - // visit https://go.microsoft.com/fwlink/?LinkID=532713 - var code = await _userManager.GeneratePasswordResetTokenAsync(user); - var callbackUrl = Url.ResetPasswordCallbackLink(user.Id, code, Request.Scheme); - await _emailSender.SendEmailAsync(model.Email, "Reset Password", - $"Please reset your password by clicking here: link"); - return RedirectToAction(nameof(ForgotPasswordConfirmation)); - } - - // If we got this far, something failed, redisplay form - return View(model); - } - - [HttpGet] - [AllowAnonymous] - public IActionResult ForgotPasswordConfirmation() - { - return View(); - } - - [HttpGet] - [AllowAnonymous] - public IActionResult ResetPassword(string code = null) - { - if (code == null) - { - throw new ApplicationException("A code must be supplied for password reset."); - } - var model = new ResetPasswordViewModel { Code = code }; - return View(model); - } - - [HttpPost] - [AllowAnonymous] - [ValidateAntiForgeryToken] - public async Task ResetPassword(ResetPasswordViewModel model) - { - if (!ModelState.IsValid) - { - return View(model); - } - var user = await _userManager.FindByEmailAsync(model.Email); - if (user == null) - { - // Don't reveal that the user does not exist - return RedirectToAction(nameof(ResetPasswordConfirmation)); - } - var result = await _userManager.ResetPasswordAsync(user, model.Code, model.Password); - if (result.Succeeded) - { - return RedirectToAction(nameof(ResetPasswordConfirmation)); - } - AddErrors(result); - return View(); - } - - [HttpGet] - [AllowAnonymous] - public IActionResult ResetPasswordConfirmation() - { - return View(); - } - -#endif #if (IndividualB2CAuth) private readonly AzureAdB2COptions _options; @@ -543,31 +126,5 @@ namespace Company.WebApplication1.Controllers { return View(); } -#if (IndividualLocalAuth) - - #region Helpers - - private void AddErrors(IdentityResult result) - { - foreach (var error in result.Errors) - { - ModelState.AddModelError(string.Empty, error.Description); - } - } - - private IActionResult RedirectToLocal(string returnUrl) - { - if (Url.IsLocalUrl(returnUrl)) - { - return Redirect(returnUrl); - } - else - { - return RedirectToAction(nameof(HomeController.Index), "Home"); - } - } - - #endregion -#endif } } diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Startup.cs b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Startup.cs index ba511285a5..ccbe1a3cdb 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Startup.cs +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Startup.cs @@ -22,9 +22,9 @@ using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Tokens; #endif #if (IndividualLocalAuth) -using Company.WebApplication1.Data; -using Company.WebApplication1.Models; -using Company.WebApplication1.Services; +using Company.WebApplication1.Identity.Data; +using Company.WebApplication1.Identity.Models; +using Company.WebApplication1.Identity.Services; #endif namespace Company.WebApplication1 @@ -53,6 +53,12 @@ namespace Company.WebApplication1 .AddEntityFrameworkStores() .AddDefaultTokenProviders(); + services.ConfigureApplicationCookie(options => { + options.LoginPath = "/tfp/Identity/Account/Login"; + options.LogoutPath = "/tfp/Identity/Account/Logout"; + options.AccessDeniedPath = "/tfp/Identity/Account/AccessDenied"; + }); + // Add application services. services.AddTransient(); diff --git a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.cshtml b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.cshtml index 2883a2e821..fe3ec2307f 100644 --- a/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.cshtml +++ b/src/Microsoft.DotNet.Web.ProjectTemplates.2.1/content/StarterWeb-CSharp/Views/Shared/_LoginPartial.cshtml @@ -9,7 +9,7 @@ #endif *@ @*#if (IndividualLocalAuth) *@ @using Microsoft.AspNetCore.Identity -@using Company.WebApplication1.Models +@using Company.WebApplication1.Identity.Models @*#else @using System.Security.Principal #endif *@ @@ -26,10 +26,10 @@ #endif *@ { @*#if (IndividualLocalAuth) *@ -