Sunday, 7 June 2020

Registration And Login Functionality In ASP.NET Core 3.0 MVC Web Application Using Identity

In this article, I will discuss how to create registration and login functionalities in ASP.NET Core web applications using Identity. ASP.NET Core Identity is an API that supports login functionality in ASP.NET Core MVC web application. 

Login information can be stored in identity when creating a new user account. Identity can be configured with SQL Server database to store user details such as username, password and email id. So in this article I will explain how to use identity to register, login and logout of a user account.
 

Creating ASP.NET Core MVC web application

 
Create ASP.NET Core MVC web application as follows
 
 
Select ASP.NET Core Web Application from the template and provide the project name and location where this project can be saved.
 
 
Select MVC template along with ASP.NET Core latest version and click on create button for the application to be created.
 
Now we have to add ASP.NET Core Identity in our application. To add identity right click on the project name, click on Add option and the click on New Scaffolded Item.
 
 
Select the Identity option and click on Add button.
 
Now we can select login and register razor pages from ASP.NET Core Identity.
 
 
Select the layout page for the razor pages, provide the data context class for database related operations and User class to customize the given registration razor page. Now click on Add button.
 
 
As we can see identity is added inside Areas folder. Inside Area folder both data as well as razor pages have been added.
 
Now we have to add user authentication into this application, for that we have to modify startup.cs class. We have to add support for razor pages inside the application.
  1. public void ConfigureServices(IServiceCollection services)  
  2.         {  
  3.             services.AddControllersWithViews();  
  4.             services.AddRazorPages();  
  5.         }  
Inside ConfigureServices method, we have to call the function AddRazorPages.
 
To include identity into this application we have to call UseAuthentication function inside configure method.
  1. app.UseAuthentication();  
Now we need to add url’s for login and register pages, for that we have to call a function called MapRazorPages inside UseEndpoints.
  1. app.UseEndpoints(endpoints =>  
  2.             {  
  3.                 endpoints.MapControllerRoute(  
  4.                     name: "default",  
  5.                     pattern: "{controller=Home}/{action=Index}/{id?}");  
  6.                 endpoints.MapRazorPages();  
  7.             });  
Now we need to create database for the application.
  1. using System.Threading.Tasks;  
  2. using Microsoft.AspNetCore.Identity;  
  3.   
  4. namespace LoginAuth.Areas.Identity.Data  
  5. {  
  6.     // Add profile data for application users by adding properties to the ApplicationUser class  
  7.     public class ApplicationUser : IdentityUser  
  8.     {  
  9.         [PersonalData]  
  10.         [Column(TypeName="nvarchar(100)")]  
  11.         public string FirstName { getset; }  
  12.   
  13.         [PersonalData]  
  14.         [Column(TypeName = "nvarchar(100)")]  
  15.         public string LirstName { getset; }  
  16.   
  17.     }  
  18. }  
Here we are adding properties for first name and last name. Inside user table it will be  personal data, that is why we need to add attribute personal data. We can also define the data types of each property with the help of attribute column.
 
Now we have to perform migration operation to insert these newly created properties inside the SQL Server database.
 
For that go to tools, then click on Nuget Package Manager. Click on Package Manager Console.
 
To create Migration, we can execute Add-Migration command.
 
 
To update the database, execute command Update-Database.
 
We can see the newly created database LoginAuthDB in SQL Server below
 
 
In order to display form controls for first name and last name inside registration form, we have to update the input model inside register.cshtml.cs file by adding corresponding properties inside the input model.
  1. public class InputModel  
  2.         {  
  3.             [Required]  
  4.             [DataType(DataType.Text)]  
  5.             [Display(Name = "First Name")]  
  6.             public string FirstName { getset; }  
  7.   
  8.             [Required]  
  9.             [DataType(DataType.Text)]  
  10.             [Display(Name = "Last Name")]  
  11.             public string LirstName { getset; }  
  12.   
  13.             [Required]  
  14.             [EmailAddress]  
  15.             [Display(Name = "Email")]  
  16.             public string Email { getset; }  
  17.   
  18.             [Required]  
  19.             [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]  
  20.             [DataType(DataType.Password)]  
  21.             [Display(Name = "Password")]  
  22.             public string Password { getset; }  
  23.   
  24.             [DataType(DataType.Password)]  
  25.             [Display(Name = "Confirm password")]  
  26.             [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]  
  27.             public string ConfirmPassword { getset; }  
  28.         }  
We also need to add the same inside the OnPostAsync function for saving the record.
  1. public async Task<IActionResult> OnPostAsync(string returnUrl = null)  
  2.         {  
  3.             returnUrl = returnUrl ?? Url.Content("~/");  
  4.             ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();  
  5.             if (ModelState.IsValid)  
  6.             {  
  7.                 var user = new ApplicationUser { UserName = Input.Email, Email = Input.Email,FirstName = Input.FirstName,LirstName = Input.LirstName };  
  8.                 var result = await _userManager.CreateAsync(user, Input.Password);  
  9.                 if (result.Succeeded)  
  10.                 {  
  11.                     _logger.LogInformation("User created a new account with password.");  
  12.   
  13.                     var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);  
  14.                     code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));  
  15.                     var callbackUrl = Url.Page(  
  16.                         "/Account/ConfirmEmail",  
  17.                         pageHandler: null,  
  18.                         values: new { area = "Identity", userId = user.Id, code = code },  
  19.                         protocol: Request.Scheme);  
  20.   
  21.                     await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",  
  22.                         $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");  
  23.   
  24.                     if (_userManager.Options.SignIn.RequireConfirmedAccount)  
  25.                     {  
  26.                         return RedirectToPage("RegisterConfirmation"new { email = Input.Email });  
  27.                     }  
  28.                     else  
  29.                     {  
  30.                         await _signInManager.SignInAsync(user, isPersistent: false);  
  31.                         return LocalRedirect(returnUrl);  
  32.                     }  
  33.                 }  
  34.                 foreach (var error in result.Errors)  
  35.                 {  
  36.                     ModelState.AddModelError(string.Empty, error.Description);  
  37.                 }  
  38.             }  
  39.   
  40.             // If we got this far, something failed, redisplay form  
  41.             return Page();  
  42.         }  
Here we are passing both first name and last name.
 
Now we need to update the registration form inside Register.cshtml
  1. @page  
  2. @model RegisterModel  
  3. @{  
  4.     ViewData["Title"] = "Register";  
  5. }  
  6.   
  7. <h1>@ViewData["Title"]</h1>  
  8.   
  9. <div class="row">  
  10.     <div class="col-md-4">  
  11.         <form asp-route-returnUrl="@Model.ReturnUrl" method="post">  
  12.             <h4>Create a new account.</h4>  
  13.             <hr />  
  14.             <div asp-validation-summary="All" class="text-danger"></div>  
  15.             <div class="form-group">  
  16.                 <label asp-for="Input.FirstName"></label>  
  17.                 <input asp-for="Input.FirstName" class="form-control" />  
  18.                 <span asp-validation-for="Input.FirstName" class="text-danger"></span>  
  19.             </div>  
  20.             <div class="form-group">  
  21.                 <label asp-for="Input.LirstName"></label>  
  22.                 <input asp-for="Input.LirstName" class="form-control" />  
  23.                 <span asp-validation-for="Input.LirstName" class="text-danger"></span>  
  24.             </div>  
  25.             <div class="form-group">  
  26.                 <label asp-for="Input.Email"></label>  
  27.                 <input asp-for="Input.Email" class="form-control" />  
  28.                 <span asp-validation-for="Input.Email" class="text-danger"></span>  
  29.             </div>  
  30.             <div class="form-group">  
  31.                 <label asp-for="Input.Password"></label>  
  32.                 <input asp-for="Input.Password" class="form-control" />  
  33.                 <span asp-validation-for="Input.Password" class="text-danger"></span>  
  34.             </div>  
  35.             <div class="form-group">  
  36.                 <label asp-for="Input.ConfirmPassword"></label>  
  37.                 <input asp-for="Input.ConfirmPassword" class="form-control" />  
  38.                 <span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>  
  39.             </div>  
  40.             <button type="submit" class="btn btn-primary">Register</button>  
  41.         </form>  
  42.     </div>  
  43.       
  44. </div>  
  45.   
  46. @section Scripts {  
  47.     <partial name="_ValidationScriptsPartial" />  
  48. }  
A new user can now register in our application. After filling the login information and clicking on login button, once the user is logged in to the application corresponding email id link and logout button can be displayed by including _LoginPartial.cshtml file inside _Logout.cshtml file as follows
  1. <!DOCTYPE html>  
  2. <html lang="en">  
  3. <head>  
  4.     <meta charset="utf-8" />  
  5.     <meta name="viewport" content="width=device-width, initial-scale=1.0" />  
  6.     <title>@ViewData["Title"] - LoginAuth</title>  
  7.     <link rel="stylesheet" href="~/lib/bootstrap/dist/css/bootstrap.min.css" />  
  8.     <link rel="stylesheet" href="~/css/site.css" />  
  9. </head>  
  10. <body>  
  11.     <header>  
  12.         <nav class="navbar navbar-expand-sm navbar-toggleable-sm navbar-light bg-white border-bottom box-shadow mb-3">  
  13.             <div class="container">  
  14.                 <a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">LoginAuth</a>  
  15.                 <button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse" aria-controls="navbarSupportedContent"  
  16.                         aria-expanded="false" aria-label="Toggle navigation">  
  17.                     <span class="navbar-toggler-icon"></span>  
  18.                 </button>  
  19.                 <div class="navbar-collapse collapse d-sm-inline-flex flex-sm-row-reverse">  
  20.                     <partial name="_LoginPartial.cshtml" />  
  21.                 </div>  
  22.             </div>  
  23.         </nav>  
  24.     </header>  
  25.     <div class="container">  
  26.         <main role="main" class="pb-3">  
  27.             @RenderBody()  
  28.         </main>  
  29.     </div>  
  30.   
  31.     <footer class="border-top footer text-muted">  
  32.         <div class="container">  
  33.             © 2020 - LoginAuth - <a asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>  
  34.         </div>  
  35.     </footer>  
  36.     <script src="~/lib/jquery/dist/jquery.min.js"></script>  
  37.     <script src="~/lib/bootstrap/dist/js/bootstrap.bundle.min.js"></script>  
  38.     <script src="~/js/site.js" asp-append-version="true"></script>  
  39.     @RenderSection("Scripts", required: false)  
  40. </body>  
  41. </html>  
We can also provide authentication feature to the application so that only authenticated users will be able to login inside the application. For that we have add Authorize attribute inside Home Controller as follows.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Diagnostics;  
  4. using System.Linq;  
  5. using System.Threading.Tasks;  
  6. using Microsoft.AspNetCore.Mvc;  
  7. using Microsoft.Extensions.Logging;  
  8. using LoginAuth.Models;  
  9. using Microsoft.AspNetCore.Authorization;  
  10.   
  11. namespace LoginAuth.Controllers  
  12. {  
  13.     [Authorize]  
  14.     public class HomeController : Controller  
  15.     {  
  16.         private readonly ILogger<HomeController> _logger;  
  17.   
  18.         public HomeController(ILogger<HomeController> logger)  
  19.         {  
  20.             _logger = logger;  
  21.         }  
  22.   
  23.         public IActionResult Index()  
  24.         {  
  25.             return View();  
  26.         }  
  27.   
  28.         public IActionResult Privacy()  
  29.         {  
  30.             return View();  
  31.         }  
  32.   
  33.         [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]  
  34.         public IActionResult Error()  
  35.         {  
  36.             return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });  
  37.         }  
  38.     }  
  39. }  
Output
 
If we run the application, we will be redirected to login page because user is not authenticated.
 
 
Registered user details are stored inside SQL Server database as follows
 
 
Once a user is logged in, the user will be redirected to the home page.
 
 

No comments:

Post a Comment