ASP.NET Core MVC Login and Registration using Identity

In this article, we will learn how to create a login and registration using identity in asp.net core. ASP.NET Core Identity provides a framework for managing and storing user accounts in ASP.NET Core apps. 

Identity is flexible enough to sync with SQL Server databases, so we’ll store login information there. Entity Framework will store user data, such as usernames and passwords. This tutorial uses ASP.NET Core Identity with a little Entity Framework magic to create smooth registration, login, and logout processes in your web application. 

Advantages of using Identity in ASP.NET Core.

  • With ASP.NET Core Identity, handling user-related tasks like registration, login, and password recovery becomes a breeze. It’s like having a personal assistant for user management.
  • Identity supports various authentication methods, allowing you to choose what works best for your application.
  • You get security features like password hashing and account lockout right out of the box.
  • Identity seamlessly integrates with Entity Framework, making it a powerhouse for storing and managing user data.
  • Easily implement role-based access control to restrict or grant access based on user roles.
  • Identity plays well with external logins so that users can sign in with their social media accounts
  • Identity is designed to seamlessly integrate with ASP.NET Core MVC, ensuring a smooth development experience.

With all these advantages and to give you a starting point, let’s cover a simple implementation of login and registration using the identity in this tutorial.

Before we start, Please make sure to have installed the following

  • The latest version of Visual Studio
  • Alternatively, you can also use the Visual Studio Code.
  • SQL Server

If you already have installed all of that, then let’s start.

Setup ASP.NET Core Web Application with Identity

1. First, create your ASP.NET Core Web Application. To do that, just follow the steps below.

  • Select File > New > Project.
  • Select ASP.NET Core Web Application. Name the project Core3.1 to have the same namespace as my project. Click OK.
  • Select an ASP.NET Core Web Application. and then uncheck Configure for HTTPS.
  • Lastly, Click on Create.
Login and Registration using Identity -ASP.NET Core Web Applciation Settings

2. Install Nuget Package

We need to install the required packages for this project. I have listed it all below.

  • Microsoft.AspNetCore.Identity.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore
  • Microsoft.EntityFrameworkCore.SqlServer
  • Microsoft.EntityFrameworkCore.Tools

Use NuGet Package Manager to install this package. If this is your first time using this, you can visit this article.

Nuget Package Manager

3. Configure Startup.cs

After gathering the necessary package, we must configure our Web Application to connect to our SQL Server. Open your Startup.cs file and follow these three simple steps.

3.1 Setup your SQL Server Configure Connection inside appsettings.json file

Appsettings.json
"ConnectionStrings": {
    "default": "Data Source=DESKTOP-4DU98BI\\SQLEXPRESS01;Initial Catalog=Codefirst;Integrated Security=True;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False"
  }

3.2 Configure your startup class by adding the below code inside the ConfigureServices method. This will read the connection string inside appsettings.json and initialize our web Application to use the SQL Server Database.

 string connectionString = Configuration.GetConnectionString("default");
 services.AddDbContext<AppDBContext>(c => c.UseSqlServer(connectionString));

3.3 To enable Authentication for our Web Application, initialize the code below inside the Configure method right above the app.UseAuthorization();

app.UseAuthentication();

4. Create a DBContext Class

To handle our database structure and queries using Entity Framework, we need to create a DBContext Class. We will handle the handshake with our Web Application and the Database. We need to extend our class to use the ASP.NET Core Identity and create its default Identity database schema to use IdentityDbContext. To see it in action, create an AppDBContext Class under the Models folder and copy the code below.

public class AppDBContext : IdentityDbContext
    {
        private readonly DbContextOptions _options;

        public AppDBContext(DbContextOptions options): base(options)
        {
            _options = options; 
        }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

        }
    }

5. Register Indentity

Now, Register Identity Services to your Web application by adding this line of code inside the ConfigureServices method. This will allow us to use Identity functionality. This class is bound with the ASP.NET Core AppDBContext Class, which handles our Database.

services.AddIdentity<IdentityUser, IdentityRole>().AddEntityFrameworkStores<AppDBContext>();

Create Migrations

Now, we need to create a migration. These steps will generate a Migration builder that contains all the Table schema we need. This schema is based on the extended properties of the IdentityDBContext Model.

  • Package Manager Console > Add-Migration IdentityDBUser
  • Visual Studio Code Terminal > dotnet ef migration add IdentityDBUser

This will create a Migration folder and classes based on ASP.NET Core Identity.

Login and Registration using Identity » MIgration Files

This migration contains a table builder based on ASP.NET Core Identity. Now, We need to create the actual tables by running a single line of code.

  • Package Manager Console > Update-Database
  • Visual Studio Code Terminal > dotnet ef database update

If we open our database, we should see a new table created with all the tables needed. If you cannot locate your database name, navigate your connection string inside appsettings.json.

Login and Registration using Identity Identity tables

We finish with the tricky part. Now, we only need to create our Models, UI, and Controller. I’ll do a straightforward step. For your reference, I’ll put an image below for my Project folder structure. Don’t worry. I will attach the link to my source code at the end of this tutorial.

Project File Structure

Login and Registration using Identity

If you are unfamiliar with the ASP.NET MVC structure, refer to this article, ASP.NET MVC File Architecture, or post your questions in the comment section.

Add View Models

1. Create RegisterViewModel Class. These will be the properties in my View.

[Required]
[EmailAddress]
public string Email { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }

[DataType(DataType.Password)]
[Display(Name ="Confirm Password")]
[Compare("Password",ErrorMessage ="Password and confirmation password not match.")]
public string ConfirmPassword { get; set; }

2. Create LoginViewModel Class.

[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; }

Create Register Action Method

1. Create a controller named AccountController. This is where all my functions for validation are located.

2. Open AccountController. Create a constructor inside the controller class and add UserManager and SignInManager. This will handle our login validation and Registration of our user identity.

private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;

public AccountController(UserManager<IdentityUser> userManager,
                              SignInManager<IdentityUser> signInManager)
    {
            _userManager = userManager;
            _signInManager = signInManager;
    }

3. Inside AccountController creates the Register method. This method will validate the input of a new user identity and register it to our database.

public IActionResult Register()
        {
            return View();
        }

        [HttpPost]
        public async Task<IActionResult> Register(RegisterViewModel model)
        {
            if (ModelState.IsValid)
            {
                var user = new IdentityUser
                {
                    UserName = model.Email,
                    Email = model.Email,
                };

                var result = await _userManager.CreateAsync(user, model.Password);

                if (result.Succeeded)
                {
                    await _signInManager.SignInAsync(user, isPersistent: false);

                    return RedirectToAction("index", "Home");
                }

                foreach (var error in result.Errors)
                {
                    ModelState.AddModelError("", error.Description);
                }

                ModelState.AddModelError(string.Empty, "Invalid Login Attempt");

            }
            return View(model);
        }

Create User Registration Form

Create and design the registration form. This view should bind to the RegisterViewModel properties so that we can use DataAnotation to prevent invalid values on our form. This function will validate our input based on the properties that we declare on our view model.

Below are the codes inside Register.cshtml.

@model SLE_System.Models.RegisterViewModel
@{
    ViewData["Title"] = "Register";
}

<h1>Register</h1>

<div class="row">
    <div class="col-md-12">
        <form method="post">
            <div asp-validation-summary="All" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Email"></label>
                <input asp-for="Email" class="form-control" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="Password"></label>
                <input asp-for="Password" class="form-control" />
                <span asp-validation-for="Password" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="ConfirmPassword"></label>
                <input asp-for="ConfirmPassword" class="form-control" />
                <span asp-validation-for="ConfirmPassword" class="text-danger"></span>
            </div>
            <button type="submit" class="btn-primary">Register</button>
        </form>

    </div>
</div>

Create Login Action Method

Create an IActionResult method and name it Login inside AccountController.

        [HttpGet]
        [AllowAnonymous]
        public IActionResult Login()
        {
            return View();
        }
        [HttpPost]
        [AllowAnonymous]
        public async Task<IActionResult> Login(LoginViewModel user)
        {
            if (ModelState.IsValid)
            {
                var result = await _signInManager.PasswordSignInAsync(user.Email, user.Password, user.RememberMe, false);

                if (result.Succeeded)
                {
                    return RedirectToAction("Index", "Home");
                }

                ModelState.AddModelError(string.Empty, "Invalid Login Attempt");

            }
            return View(user);
        } 

Create a User Login Form

Add View name Login.cshtml. This view should be inside Views > Account. Copy the codes below.

@model SLE_System.Models.LoginViewModel
@{
    ViewData["Title"] = "Login";
}

<h1>Login</h1>

<div class="row">
    <div class="col-md-12">
        <form method="post">
            <div asp-validation-summary="All" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Email"></label>
                <input asp-for="Email" class="form-control" />
                <span asp-validation-for="Email" class="text-danger"></span>
            </div>

            <div class="form-group">
                <label asp-for="Password"></label>
                <input asp-for="Password" class="form-control" />
                <span asp-validation-for="Password" class="text-danger"></span>
            </div>

            <div class="form-group">
                <div class="custom-control custom-checkbox">
                    <input asp-for="RememberMe" type="checkbox" class="custom-control-input">
                    <label class="custom-control-label" asp-for="RememberMe">@Html.DisplayNameFor(m => m.RememberMe)</label>
                </div>

            </div>
            <button type="submit" class="btn-primary">Login</button>
        </form>

    </div>
</div>

Create Logout Action Method

Create the IActionResult method inside AccountController. Name it Logout().

public async Task<IActionResult> Logout()
        {
            await _signInManager.SignOutAsync();

            return RedirectToAction("Login");
        }

Modify Navigation Menu

Now, we need to customize which menu will be visible for an unauthenticated user. To do that, open your Shared Folder under Views and select _Layout view. This view handles the main layout of your Web Application.

Main Layout View
_layout.cshtml

One way to handle this is to drop to C# code and use User Identity to check the user’s validity. Please refer to the code below.

@if (User.Identity.IsAuthenticated)
                    {
                    <ul class="navbar-nav flex-grow-1">
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Index">Home</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Home" asp-action="Privacy">Privacy</a>
                        </li>
                        <li class="nav-item">
                            <a class="nav-link text-dark" asp-area="" asp-controller="Account" asp-action="Logout">Logout</a>
                        </li>
                    </ul>
                    }
                    else
                    {
                        <ul class="navbar-nav flex-grow-1">
                            <li class="nav-item">
                                <a class="nav-link text-dark" asp-area="" asp-controller="Account" asp-action="Login">Login</a>
                            </li>
                            <li class="nav-item">
                                <a class="nav-link text-dark" asp-area="" asp-controller="Account" asp-action="Register">Register</a>
                            </li>
                        </ul>
                    } 

Suppose you have followed all the steps above. You have fully implemented a Web Application with Login and Registration using Identity in ASP.NET Core 3.1. We use ASP.NET Core Entity Framework in this. If this confused you, let me know how to improve my writing style by commenting below.

I will attach a link to my GitHub repository below. Don’t forget to leave a comment. Thank you! Happy coding!.

Download Source Code

To download free source code from this tutorial, you can use the button below.

Note: Extract the file using 7Zip and use password: freecodespot

Summary

In conclusion, leveraging Identity in ASP.NET Core to build a login and registration system offers a strong option for handling your application’s user authentication and account management. You can ensure your system is secure and effective by following the tutorial’s instructions carefully. This is just a simple implementation of how to use Identity in ASP.NET Core; we can expand this by using role-based authentication to make it more secure. If this tutorial helps you, feel free to share it with your friends. Thank you.

Keep Coding!