Using Identity In ASP.NET Core MVC Authentication

Introduction

This article explains how to get started with Identity.UI in ASP.Net Core MVC user authentication and registration.

Link to download the project source code here.

Step 1. Let's create an ASP.NET Core web application. Open Visual Studio 2019 and click on Create a new project.

New project

Select ASP.NET Core Web Application, and click on Next.

Web Application

Provide the project name of your choice, select the preferred location & click on Create.

Project name

Select MVC Template and click on Create, as shown below.

MVC Template

Step 2. Now let's add an ASP.NET Core Identity. Select the project > Right-click > Add > Click on the New Scaffold item.

 Core Identity

Select Identity and click on add.

Select Identity

Now select the layout page, as we want authentication. Let's select login and Register as shown below provide the DbContext class and user class and click on Add.

DbContext class

We can find the Areas in the application with Data & Razor pages, as shown below.

Data & Razor

Step 3. Now let's add user authentication to the application. Open the Startup class and Modify as shown below.

In order to add support to the razor pages, we have to call the function services.AddRazorPages() and endpoints.MapRazorPages().

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddRazorPages();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
            // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
            app.UseHsts();
        }
        app.UseHttpsRedirection();
        app.UseStaticFiles();

        app.UseRouting();
        app.UseAuthentication();
        app.UseAuthorization();

        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllerRoute(
                name: "default",
                pattern: "{controller=Home}/{action=Index}/{id?}");
            endpoints.MapRazorPages();
        });
    }
}

Step 4. Now let's start with creating the database for the application.

Open UsingIdentityUser class and add the properties and decorate with the attribute PersonalData.

public class UsingIdentityUser : IdentityUser
{
    [PersonalData]
    [Column(TypeName = "nvarchar(100)")]
    public string Firstname { get; set; }

    [PersonalData]
    [Column(TypeName = "nvarchar(100)")]
    public string LastName { get; set; }
}

We have Dbcontext, which is also inherited from the parent class IdentityDB context. This identity db context is injected inside this identityhostingstartup class.

public class IdentityHostingStartup : IHostingStartup
{
    public void Configure(IWebHostBuilder builder)
    {
        builder.ConfigureServices((context, services) =>
        {
            services.AddDbContext<UsingIdentityContext>(options =>
                options.UseSqlServer(
                    context.Configuration.GetConnectionString("UsingIdentityContextConnection")));

            services.AddDefaultIdentity<UsingIdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
                .AddEntityFrameworkStores<UsingIdentityContext>();
        });
    }
}

Now open appsttings.json. We can find the connection string with the name UsingIdentityContextConnection. By default, it will connect to the local DB.

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "UsingIdentityContextConnection": "Server=SAGAR;Database=UsingIdentityDB;Trusted_Connection=True;MultipleActiveResultSets=true"
  }
}

Now open the Package manager console and Execute the command Add-Migration "First-Create" to generate the actual physical DB

Package manager

Finally, execute the command Update-Database and you can find the new database as shown below.

Update-Database

New database

Step 5. Now let's start customizing the application. Let's add a Nested layout for tab control headers.

 Nested layout

Select Razor layout and click on Add.

 Razor layout

Customize the layout as below.

@{
    Layout = "/Views/Shared/_Layout.cshtml";
}

<div class="row">
    <div class="col-md-6 offset-md-3">
        <div class="card login-logout-tab">
            <div class="card-header">
                <ul class="nav nav-tabs card-header-tabs">
                    <li class="nav-item">
                        <a class="nav-link" href="/Identity/Account/Login">Log In</a>
                    </li>
                    <li class="nav-item">
                        <a class="nav-link" href="/Identity/Account/Register">Sign Up </a>
                    </li>
                </ul>
            </div>
            <div class="card-content">
                <div class="row">
                    <div class="col-md-12">
                        @RenderBody()
                    </div>
                </div>
            </div>
        </div>
    </div>
</div>

@section Scripts{

    @RenderSection("Scripts", required: false)
    <script>
        $(function () {

            var current = location.pathname;
            $('.nav-tabs li a').each(function () {
                var $this = $(this);
                if (current.indexOf($this.attr('href')) !== -1) {
                    $this.addClass('active');
                }
            })
        })
    </script>
}

Open site.css and use the below styles.

/* for Tab control */
div.login-logout-tab div.card.header {
    padding: 0px 0px 12px 0px;
}

div.login-logout-tab li.nav-tabs {
    margin: 0px 0px -12px 0px;
}

div.login-logout-tab li.nav-item {
    width: 50%;
}

div.login-logout-tab a.nav-link {
    font-size: 25px;
    color: #495057;
    text-align: center;
}

Modify the Login page and register the HTML pages with our new layout.

@page
@model LoginModel

@{
    ViewData["Title"] = "Log in";
    Layout = "~/Areas/Identity/Pages/_IdentityLayout.cshtml";
}

<div class="col-md-10 offset-md-1">
    <section>
        @*<div class="login-form-icon">
            <i class="fas fa-user-circle fa-5x text-secondary"></i>
        </div>*@
        @*fas fa-user-circle fa-9x text-secondary*@
        <form id="account" method="post">
            <div asp-validation-summary="All" class="text-danger"></div>
            <div class="form-group">
                <label asp-for="Input.Email"></label>
                <input asp-for="Input.Email" class="form-control" />
                <span asp-validation-for="Input.Email" class="text-danger"></span>
            </div>
            <div class="form-group">
                <label asp-for="Input.Password"></label>
                <input asp-for="Input.Password" class="form-control" />
                <span asp-validation-for="Input.Password" class="text-danger"></span>
            </div>
            <div class="form-group">
                <div class="checkbox">
                    <label asp-for="Input.RememberMe">
                        <input asp-for="Input.RememberMe" />
                        @Html.DisplayNameFor(m => m.Input.RememberMe)
                    </label>
                </div>
            </div>
            <div class="form-group">
                <button type="submit" class="btn btn-primary btn-block">Log in</button>
            </div>
        </form>

    </section>
</div>

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

@page
@model RegisterModel
@{
    ViewData["Title"] = "Register";
    Layout = "~/Areas/Identity/Pages/_IdentityLayout.cshtml";
}

<h1>@ViewData["Title"]</h1>


<form asp-route-returnUrl="@Model.ReturnUrl" method="post">
    <div asp-validation-summary="All" class="text-danger"></div>
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Input.FirstName"></label>
                <input asp-for="Input.FirstName" class="form-control" />
                <span asp-validation-for="Input.FirstName" class="text-danger"></span>
            </div>
        </div>

        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Input.LastName"></label>
                <input asp-for="Input.LastName" class="form-control" />
                <span asp-validation-for="Input.LastName" class="text-danger"></span>
            </div>
        </div>
    </div>
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Input.Email"></label>
                <input asp-for="Input.Email" class="form-control" />
                <span asp-validation-for="Input.Email" class="text-danger"></span>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Input.PhoneNumber"></label>
                <input asp-for="Input.PhoneNumber" class="form-control" />
                <span asp-validation-for="Input.PhoneNumber" class="text-danger"></span>
            </div>
        </div>
    </div>
        
    <div class="row">
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Input.Password"></label>
                <input asp-for="Input.Password" class="form-control" />
                <span asp-validation-for="Input.Password" class="text-danger"></span>
            </div>
        </div>
        <div class="col-md-6">
            <div class="form-group">
                <label asp-for="Input.ConfirmPassword"></label>
                <input asp-for="Input.ConfirmPassword" class="form-control" />
                <span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
            </div>
        </div>
    </div>

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

@section Scripts {
    <partial name="_ValidationScriptsPartial" />
}

In order to display the active tab, we need to add an active class, as shown below.

@section Scripts {
    @RenderSection("Scripts", required: false)
    <script>
        $(function () {
            var current = location.pathname;
            $('.nav-tabs li a').each(function () {
                var $this = $(this);
                if (current.indexOf($this.attr('href')) !== -1) {
                    $this.addClass('active');
                }
            })
        })
    </script>
}

Let's see the output and register a user.

Output

Register a user

Now let's log in with the registered user.

Registered user

Welcome

Conclusion

In this article, we discussed how to use Identity UI in ASP.NET Core MVC application by creating a database using the package manager console & commands. I hope you all enjoyed reading this and learned from it.


Similar Articles