ASP.NET Core Identity Authentication

Authentication in ASP.NET Core Identity

ASP.NET Core Identity provides a rich set of features for handling user authentication and authorization in your applications. This section delves into the core concepts and implementation details of authentication using ASP.NET Core Identity.

Core Concepts

Authentication Middleware

The authentication middleware is a crucial component that intercepts incoming HTTP requests and determines the identity of the caller. ASP.NET Core Identity integrates with the ASP.NET Core authentication middleware pipeline to handle various authentication schemes.

Authentication Schemes

An authentication scheme defines how an application authenticates a user. ASP.NET Core Identity supports multiple schemes, including:

IAuthenticationService

The IAuthenticationService is responsible for orchestrating the authentication process. It uses configured authentication handlers to validate credentials and create a ClaimsPrincipal representing the authenticated user.

Implementing Authentication

Configuring Authentication Services

Authentication is typically configured in the Program.cs (or Startup.cs in older versions) file:


using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using YourApp.Data; // Assuming you have a DbContext named ApplicationDbContext

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlServer(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddEntityFrameworkStores<ApplicationDbContext>();

// Add cookie authentication
builder.Services.AddAuthentication(options =>
{
    options.DefaultScheme = IdentityConstants.ApplicationScheme;
    options.DefaultChallengeScheme = IdentityConstants.ApplicationScheme;
    options.DefaultSignInScheme = IdentityConstants.ExternalScheme;
})
.AddCookie(IdentityConstants.ApplicationScheme, options =>
{
    options.LoginPath = "/Account/Login";
    options.LogoutPath = "/Account/Logout";
    options.AccessDeniedPath = "/Account/AccessDenied";
});

builder.Services.AddControllersWithViews();

var app = builder.Build();

// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
else
{
    app.UseExceptionHandler("/Home/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseRouting();

// Add authentication and authorization middleware
app.UseAuthentication();
app.UseAuthorization();

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

app.Run();
            

Login and Logout

You'll typically create controller actions and Razor Pages for handling user login and logout. The SignInManager<TUser> and UserManager<TUser> services are used extensively here.

Login Action Example


[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl)
{
    if (ModelState.IsValid)
    {
        var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
        if (result.Succeeded)
        {
            return LocalRedirect(returnUrl);
        }
        if (result.IsLockedOut)
        {
            // Handle locked out user
        }
        else
        {
            ModelState.AddModelError(string.Empty, "Invalid login attempt.");
            return View(model);
        }
    }
    return View(model);
}
            

Logout Action Example


[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout()
{
    await _signInManager.SignOutAsync();
    return RedirectToAction("Index", "Home");
}
            

Securing Endpoints

You can protect controller actions or Razor Pages using the [Authorize] attribute.


[Authorize]
public class SecureController : Controller
{
    // ...
}

[Authorize(Roles = "Admin")]
public IActionResult AdminDashboard()
{
    // ...
}
            
Note: The [Authorize] attribute relies on the configured authentication middleware to identify the user. Ensure that app.UseAuthentication() and app.UseAuthorization() are called in the correct order in your application's request pipeline.

Authentication Handlers

Each authentication scheme is implemented by an authentication handler. ASP.NET Core Identity provides built-in handlers for cookie authentication. You can also create custom handlers for more advanced scenarios.

Further Reading