 b24beb3154
			
		
	
	
		b24beb3154
		
	
	
	
	
		
			
			This commit integrates ASP.NET Core Identity into the application to enable user registration, login, and management. This lays the groundwork for securing data per user.
**Key Changes:**
*   **DbContext Configuration:**
    *   Modified `ApplicationDbContext.cs` to inherit from `IdentityDbContext<IdentityUser>`.
    *   Removed an unnecessary `using` statement from `ApplicationDbContext.cs`.
*   **Program.cs Setup:**
    *   Configured `AddDefaultIdentity<IdentityUser>` with `AddEntityFrameworkStores<ApplicationDbContext>()` to register Identity services.
    *   Ensured correct ordering of `UseAuthentication()` and `UseAuthorization()` middleware.
    *   Added `app.MapRazorPages()` to enable the Identity UI pages.
    *   Verified core package versions in `turf_tasker.csproj` for consistency across EF Core and Identity components (`8.0.6`).
*   **Identity UI:**
    *   Scaffolded ASP.NET Core Identity pages (Login, Register, Manage, etc.) to provide the user interface for authentication.
    *   Added a `_LoginPartial.cshtml` partial view to the `Views/Shared` folder.
    *   Rendered `_LoginPartial` in `Views/Shared/_Layout.cshtml` to display login/register/logout links in the navigation bar.
*   **Migrations:**
    *   Created and applied a new migration (`AddIdentitySchema`) to create the necessary ASP.NET Core Identity database tables (e.g., `AspNetUsers`, `AspNetRoles`).
		
	
			
		
			
				
	
	
		
			141 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			141 lines
		
	
	
	
		
			5.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| // Licensed to the .NET Foundation under one or more agreements.
 | |
| // The .NET Foundation licenses this file to you under the MIT license.
 | |
| #nullable disable
 | |
| 
 | |
| using System;
 | |
| using System.Collections.Generic;
 | |
| using System.Linq;
 | |
| using System.Threading;
 | |
| using System.Threading.Tasks;
 | |
| using Microsoft.AspNetCore.Authentication;
 | |
| using Microsoft.AspNetCore.Identity;
 | |
| using Microsoft.AspNetCore.Mvc;
 | |
| using Microsoft.AspNetCore.Mvc.RazorPages;
 | |
| 
 | |
| namespace turf_tasker.Areas.Identity.Pages.Account.Manage
 | |
| {
 | |
|     public class ExternalLoginsModel : PageModel
 | |
|     {
 | |
|         private readonly UserManager<IdentityUser> _userManager;
 | |
|         private readonly SignInManager<IdentityUser> _signInManager;
 | |
|         private readonly IUserStore<IdentityUser> _userStore;
 | |
| 
 | |
|         public ExternalLoginsModel(
 | |
|             UserManager<IdentityUser> userManager,
 | |
|             SignInManager<IdentityUser> signInManager,
 | |
|             IUserStore<IdentityUser> userStore)
 | |
|         {
 | |
|             _userManager = userManager;
 | |
|             _signInManager = signInManager;
 | |
|             _userStore = userStore;
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
 | |
|         ///     directly from your code. This API may change or be removed in future releases.
 | |
|         /// </summary>
 | |
|         public IList<UserLoginInfo> CurrentLogins { get; set; }
 | |
| 
 | |
|         /// <summary>
 | |
|         ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
 | |
|         ///     directly from your code. This API may change or be removed in future releases.
 | |
|         /// </summary>
 | |
|         public IList<AuthenticationScheme> OtherLogins { get; set; }
 | |
| 
 | |
|         /// <summary>
 | |
|         ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
 | |
|         ///     directly from your code. This API may change or be removed in future releases.
 | |
|         /// </summary>
 | |
|         public bool ShowRemoveButton { get; set; }
 | |
| 
 | |
|         /// <summary>
 | |
|         ///     This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
 | |
|         ///     directly from your code. This API may change or be removed in future releases.
 | |
|         /// </summary>
 | |
|         [TempData]
 | |
|         public string StatusMessage { get; set; }
 | |
| 
 | |
|         public async Task<IActionResult> OnGetAsync()
 | |
|         {
 | |
|             var user = await _userManager.GetUserAsync(User);
 | |
|             if (user == null)
 | |
|             {
 | |
|                 return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
 | |
|             }
 | |
| 
 | |
|             CurrentLogins = await _userManager.GetLoginsAsync(user);
 | |
|             OtherLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync())
 | |
|                 .Where(auth => CurrentLogins.All(ul => auth.Name != ul.LoginProvider))
 | |
|                 .ToList();
 | |
| 
 | |
|             string passwordHash = null;
 | |
|             if (_userStore is IUserPasswordStore<IdentityUser> userPasswordStore)
 | |
|             {
 | |
|                 passwordHash = await userPasswordStore.GetPasswordHashAsync(user, HttpContext.RequestAborted);
 | |
|             }
 | |
| 
 | |
|             ShowRemoveButton = passwordHash != null || CurrentLogins.Count > 1;
 | |
|             return Page();
 | |
|         }
 | |
| 
 | |
|         public async Task<IActionResult> OnPostRemoveLoginAsync(string loginProvider, string providerKey)
 | |
|         {
 | |
|             var user = await _userManager.GetUserAsync(User);
 | |
|             if (user == null)
 | |
|             {
 | |
|                 return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
 | |
|             }
 | |
| 
 | |
|             var result = await _userManager.RemoveLoginAsync(user, loginProvider, providerKey);
 | |
|             if (!result.Succeeded)
 | |
|             {
 | |
|                 StatusMessage = "The external login was not removed.";
 | |
|                 return RedirectToPage();
 | |
|             }
 | |
| 
 | |
|             await _signInManager.RefreshSignInAsync(user);
 | |
|             StatusMessage = "The external login was removed.";
 | |
|             return RedirectToPage();
 | |
|         }
 | |
| 
 | |
|         public async Task<IActionResult> OnPostLinkLoginAsync(string provider)
 | |
|         {
 | |
|             // Clear the existing external cookie to ensure a clean login process
 | |
|             await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
 | |
| 
 | |
|             // Request a redirect to the external login provider to link a login for the current user
 | |
|             var redirectUrl = Url.Page("./ExternalLogins", pageHandler: "LinkLoginCallback");
 | |
|             var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl, _userManager.GetUserId(User));
 | |
|             return new ChallengeResult(provider, properties);
 | |
|         }
 | |
| 
 | |
|         public async Task<IActionResult> OnGetLinkLoginCallbackAsync()
 | |
|         {
 | |
|             var user = await _userManager.GetUserAsync(User);
 | |
|             if (user == null)
 | |
|             {
 | |
|                 return NotFound($"Unable to load user with ID '{_userManager.GetUserId(User)}'.");
 | |
|             }
 | |
| 
 | |
|             var userId = await _userManager.GetUserIdAsync(user);
 | |
|             var info = await _signInManager.GetExternalLoginInfoAsync(userId);
 | |
|             if (info == null)
 | |
|             {
 | |
|                 throw new InvalidOperationException($"Unexpected error occurred loading external login info.");
 | |
|             }
 | |
| 
 | |
|             var result = await _userManager.AddLoginAsync(user, info);
 | |
|             if (!result.Succeeded)
 | |
|             {
 | |
|                 StatusMessage = "The external login was not added. External logins can only be associated with one account.";
 | |
|                 return RedirectToPage();
 | |
|             }
 | |
| 
 | |
|             // Clear the existing external cookie to ensure a clean login process
 | |
|             await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);
 | |
| 
 | |
|             StatusMessage = "The external login was added.";
 | |
|             return RedirectToPage();
 | |
|         }
 | |
|     }
 | |
| }
 |