Step 1: Project Setup & NuGet Packages
First, create a new ASP.NET Core MVC project using the .NET CLI:
Bash
dotnet new mvc -n MvcAuthenticationDemo
cd MvcAuthenticationDemo
Next, ensure you have the required Entity Framework Core and Identity packages installed (these are typically included by default or via EF Core templates):
Bash
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.Tools
dotnet add package Microsoft.AspNetCore.Identity.EntityFrameworkCore
Step 2: Creating the Application Context
Inherit from IdentityDbContext to enable Entity Framework Core to manage your users, roles, and authentication tables.
Create a folder named Data and add a file called ApplicationDbContext.cs:
C#
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using MvcAuthenticationDemo.Models;
namespace MvcAuthenticationDemo.Data
{
public class ApplicationDbContext : IdentityDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
}
}
Step 3: Configuring Services in Program.cs
Register the database context and the Identity services inside Program.cs. Ensure that .AddEntityFrameworkStores<ApplicationDbContext>() and cookie settings are properly configured.
C#
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using MvcAuthenticationDemo.Data;
var builder = WebApplication.CreateBuilder(args);
// 1. Add DbContext with SQL Server
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
// 2. Add Default Identity
builder.Services.AddDefaultIdentity<IdentityUser>(options =>
{
options.SignIn.RequireConfirmedAccount = false;
options.Password.RequireDigit = true;
options.Password.RequiredLength = 6;
options.Password.NonAlphanumeric = false;
})
.AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
// 3. Enable Authentication & Authorization Middleware
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Add your connection string to appsettings.json:
JSON
{
"ConnectionStrings": {
"DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=MvcAuthDb;Trusted_Connection=True;MultipleActiveResultSets=true"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore.Authorization": "Warning"
}
},
"AllowedHosts": "*"
}
Step 4: Creating the Account Controller
Create an AccountController to manage user registration, login, and logout operations using ASP.NET Core's UserManager and SignInManager.
Create Controllers/AccountController.cs:
C#
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using MvcAuthenticationDemo.Models;
namespace MvcAuthenticationDemo.Controllers
{
public class AccountController : Controller
{
private readonly UserManager<IdentityUser> _userManager;
private readonly SignInManager<IdentityUser> _signInManager;
public AccountController(UserManager<IdentityUser> userManager, SignInManager<IdentityUser> signInManager)
{
_userManager = userManager;
_signInManager = signInManager;
}
// GET: /Account/Register
[HttpGet]
public IActionResult Register() => View();
// POST: /Account/Register
[HttpPost]
[ValidateAntiForgeryToken]
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(string.Empty, error.Description);
}
}
return View(model);
}
// GET: /Account/Login
[HttpGet]
public IActionResult Login(string? returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
return View();
}
// POST: /Account/Login
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string? returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded)
{
return LocalRedirect(returnUrl ?? "~/");
}
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
}
return View(model);
}
// POST: /Account/Logout
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout()
{
await _signInManager.SignOutAsync();
return RedirectToAction("Index", "Home");
}
}
}
Step 5: Creating View Models
Create a folder named Models and add view models for handling form inputs securely.
Models/RegisterViewModel.cs:
C#
using System.ComponentModel.DataAnnotations;
namespace MvcAuthenticationDemo.Models
{
public class RegisterViewModel
{
[Required, EmailAddress]
public string Email { get; set; } = string.Empty;
[Required, DataType(DataType.Password)]
public string Password { get; set; } = string.Empty;
[DataType(DataType.Password), Display(Name = "Confirm password")]
[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
public string ConfirmPassword { get; set; } = string.Empty;
}
}
Models/LoginViewModel.cs:
C#
using System.ComponentModel.DataAnnotations;
namespace MvcAuthenticationDemo.Models
{
public class LoginViewModel
{
[Required, EmailAddress]
public string Email { get; set; } = string.Empty;
[Required, DataType(DataType.Password)]
public string Password { get; set; } = string.Empty;
[Display(Name = "Remember me?")]
public bool RememberMe { get; set; }
}
}
Step 6: Protecting Controllers and Views
You can secure any controller or action method by applying the [Authorize] attribute. If an unauthenticated user tries to access it, ASP.NET Core will automatically redirect them to the login page.
C#
[Authorize]
public class DashboardController : Controller
{
public IActionResult Index()
{
return View();
}
}
To conditionally show login/logout links in your layout (Views/Shared/_Layout.cshtml), check the user's authentication state:
HTML
<ul class="navbar-nav ms-auto">
@if (User.Identity != null && User.Identity.IsAuthenticated)
{
<li class="nav-item">
<span class="nav-link text-dark">Hello @User.Identity.Name!</span>
</li>
<li class="nav-item">
<form class="form-inline" asp-controller="Account" asp-action="Logout" method="post">
<button type="submit" class="nav-link btn btn-link text-dark">Logout</button>
</form>
</li>
}
else
{
<li class="nav-item">
<a class="nav-link text-dark" asp-controller="Account" asp-action="Register">Register</a>
</li>
<li class="nav-item">
<a class="nav-link text-dark" asp-controller="Account" asp-action="Login">Login</a>
</li>
}
</ul>
Step 7: Applying Migrations and Testing
Run the following commands in your terminal to create the database schema:
Bash
dotnet ef migrations add InitialCreate
dotnet ef database update
Run your project using dotnet run, navigate to /Account/Register to create a new user account and test your secured authentication flow!

Join the conversation! Your thoughts help the community grow.