diff --git a/src/Web/Areas/Identity/IdentityHostingStartup.cs b/src/Web/Areas/Identity/IdentityHostingStartup.cs
new file mode 100644
index 0000000..57a55bd
--- /dev/null
+++ b/src/Web/Areas/Identity/IdentityHostingStartup.cs
@@ -0,0 +1,21 @@
+using System;
+using Microsoft.AspNetCore.Hosting;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Identity.UI;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.eShopWeb.Infrastructure.Identity;
+using Microsoft.Extensions.Configuration;
+using Microsoft.Extensions.DependencyInjection;
+
+[assembly: HostingStartup(typeof(Microsoft.eShopWeb.Web.Areas.Identity.IdentityHostingStartup))]
+namespace Microsoft.eShopWeb.Web.Areas.Identity
+{
+ public class IdentityHostingStartup : IHostingStartup
+ {
+ public void Configure(IWebHostBuilder builder)
+ {
+ builder.ConfigureServices((context, services) => {
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Web/Areas/Identity/Pages/Account/Login.cshtml b/src/Web/Areas/Identity/Pages/Account/Login.cshtml
new file mode 100644
index 0000000..e3bbc04
--- /dev/null
+++ b/src/Web/Areas/Identity/Pages/Account/Login.cshtml
@@ -0,0 +1,63 @@
+@page
+@model LoginModel
+
+@{
+ ViewData["Title"] = "Log in";
+}
+
+
@ViewData["Title"]
+
+
+@section Scripts {
+
+}
diff --git a/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs b/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs
new file mode 100644
index 0000000..72ecf94
--- /dev/null
+++ b/src/Web/Areas/Identity/Pages/Account/Login.cshtml.cs
@@ -0,0 +1,103 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel.DataAnnotations;
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Identity;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+using Microsoft.eShopWeb.Infrastructure.Identity;
+using Microsoft.Extensions.Logging;
+
+namespace Microsoft.eShopWeb.Web.Areas.Identity.Pages.Account
+{
+ [AllowAnonymous]
+ public class LoginModel : PageModel
+ {
+ private readonly SignInManager _signInManager;
+ private readonly ILogger _logger;
+
+ public LoginModel(SignInManager signInManager, ILogger logger)
+ {
+ _signInManager = signInManager;
+ _logger = logger;
+ }
+
+ [BindProperty]
+ public InputModel Input { get; set; }
+
+ public IList ExternalLogins { get; set; }
+
+ public string ReturnUrl { get; set; }
+
+ [TempData]
+ public string ErrorMessage { get; set; }
+
+ public class InputModel
+ {
+ [Required]
+ [EmailAddress]
+ public string Email { get; set; }
+
+ [Required]
+ [DataType(DataType.Password)]
+ public string Password { get; set; }
+
+ [Display(Name = "Remember me?")]
+ public bool RememberMe { get; set; }
+ }
+
+ public async Task OnGetAsync(string returnUrl = null)
+ {
+ if (!string.IsNullOrEmpty(ErrorMessage))
+ {
+ ModelState.AddModelError(string.Empty, ErrorMessage);
+ }
+
+ returnUrl = returnUrl ?? Url.Content("~/");
+
+ // Clear the existing external cookie to ensure a clean login process
+ await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
+
+ ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
+
+ ReturnUrl = returnUrl;
+ }
+
+ public async Task OnPostAsync(string returnUrl = null)
+ {
+ returnUrl = returnUrl ?? Url.Content("~/");
+
+ 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(Input.Email, Input.Password, Input.RememberMe, lockoutOnFailure: true);
+ if (result.Succeeded)
+ {
+ _logger.LogInformation("User logged in.");
+ return LocalRedirect(returnUrl);
+ }
+ if (result.RequiresTwoFactor)
+ {
+ return RedirectToPage("./LoginWith2fa", new { ReturnUrl = returnUrl, RememberMe = Input.RememberMe });
+ }
+ if (result.IsLockedOut)
+ {
+ _logger.LogWarning("User account locked out.");
+ return RedirectToPage("./Lockout");
+ }
+ else
+ {
+ ModelState.AddModelError(string.Empty, "Invalid login attempt.");
+ return Page();
+ }
+ }
+
+ // If we got this far, something failed, redisplay form
+ return Page();
+ }
+ }
+}
diff --git a/src/Web/Areas/Identity/Pages/Account/_ViewImports.cshtml b/src/Web/Areas/Identity/Pages/Account/_ViewImports.cshtml
new file mode 100644
index 0000000..65840eb
--- /dev/null
+++ b/src/Web/Areas/Identity/Pages/Account/_ViewImports.cshtml
@@ -0,0 +1 @@
+@using Microsoft.eShopWeb.Web.Areas.Identity.Pages.Account
\ No newline at end of file
diff --git a/src/Web/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml b/src/Web/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml
new file mode 100644
index 0000000..bacc0ae
--- /dev/null
+++ b/src/Web/Areas/Identity/Pages/_ValidationScriptsPartial.cshtml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
diff --git a/src/Web/Areas/Identity/Pages/_ViewImports.cshtml b/src/Web/Areas/Identity/Pages/_ViewImports.cshtml
new file mode 100644
index 0000000..82c4f63
--- /dev/null
+++ b/src/Web/Areas/Identity/Pages/_ViewImports.cshtml
@@ -0,0 +1,5 @@
+@using Microsoft.AspNetCore.Identity
+@using Microsoft.eShopWeb.Web.Areas.Identity
+@using Microsoft.eShopWeb.Infrastructure.Identity
+@namespace Microsoft.eShopWeb.Web.Areas.Identity.Pages
+@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
diff --git a/src/Web/Startup.cs b/src/Web/Startup.cs
index f35bd23..93d399a 100644
--- a/src/Web/Startup.cs
+++ b/src/Web/Startup.cs
@@ -114,11 +114,13 @@ namespace Microsoft.eShopWeb.Web
{
options.Conventions.Add(new RouteTokenTransformerConvention(
new SlugifyParameterTransformer()));
+
}
)
.AddRazorPagesOptions(options =>
{
options.Conventions.AuthorizePage("/Basket/Checkout");
+ options.AllowAreas = true;
})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
@@ -164,7 +166,6 @@ namespace Microsoft.eShopWeb.Web
{
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromHours(1);
- options.LoginPath = "/Account/Signin";
options.LogoutPath = "/Account/Signout";
options.Cookie = new CookieBuilder
{
diff --git a/src/Web/Views/Shared/_LoginPartial.cshtml b/src/Web/Views/Shared/_LoginPartial.cshtml
index fce87e4..1f454f6 100644
--- a/src/Web/Views/Shared/_LoginPartial.cshtml
+++ b/src/Web/Views/Shared/_LoginPartial.cshtml
@@ -40,7 +40,7 @@ else
diff --git a/src/Web/Web.csproj b/src/Web/Web.csproj
index c27268f..c27cb26 100644
--- a/src/Web/Web.csproj
+++ b/src/Web/Web.csproj
@@ -18,6 +18,7 @@
+