ASP.NET MVC
User Authentication
User Authorization
Web Security
Access Control

User authentication and authorisation in ASP.NET MVC

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Authentication and authorization are related, but they solve different security questions in an ASP.NET MVC application. Authentication answers who the user is, while authorization decides what that user is allowed to access after sign-in succeeds.

Authentication in ASP.NET MVC

In a typical MVC application, authentication starts with a login form. The user submits credentials, the server validates them, and then the app issues an authentication cookie so later requests can be associated with that identity.

With ASP.NET Identity, that flow is usually managed by UserManager and SignInManager.

csharp
1using Microsoft.AspNetCore.Identity;
2using Microsoft.AspNetCore.Mvc;
3
4public class AccountController : Controller
5{
6    private readonly SignInManager<IdentityUser> _signInManager;
7
8    public AccountController(SignInManager<IdentityUser> signInManager)
9    {
10        _signInManager = signInManager;
11    }
12
13    [HttpPost]
14    public async Task<IActionResult> Login(string email, string password)
15    {
16        var result = await _signInManager.PasswordSignInAsync(
17            email,
18            password,
19            isPersistent: false,
20            lockoutOnFailure: true);
21
22        if (result.Succeeded)
23        {
24            return RedirectToAction("Index", "Home");
25        }
26
27        ModelState.AddModelError("", "Invalid login attempt.");
28        return View();
29    }
30}

The important point is that login code should not just compare plain text passwords. Use the framework identity system so password hashing, cookie generation, lockout rules, and security stamp validation are handled correctly.

Authorization after login

Once a user is authenticated, authorization rules determine which controllers or actions they can reach. In MVC, the most direct mechanism is the [Authorize] attribute.

csharp
1using Microsoft.AspNetCore.Authorization;
2using Microsoft.AspNetCore.Mvc;
3
4[Authorize]
5public class OrdersController : Controller
6{
7    public IActionResult Index()
8    {
9        return View();
10    }
11}

That attribute requires a signed-in user. You can narrow access further with roles or policies.

csharp
1[Authorize(Roles = "Admin")]
2public IActionResult AdminDashboard()
3{
4    return View();
5}

Policies are more flexible because they let you express business rules that are not just role names.

csharp
1builder.Services.AddAuthorization(options =>
2{
3    options.AddPolicy("CanApproveInvoices", policy =>
4        policy.RequireClaim("permission", "approve_invoices"));
5});
csharp
1[Authorize(Policy = "CanApproveInvoices")]
2public IActionResult Approve()
3{
4    return View();
5}

This keeps permission checks centralized instead of scattering string comparisons across controllers.

Configuration essentials

Your application also needs middleware and service registration so authentication and authorization are active for every request.

csharp
1var builder = WebApplication.CreateBuilder(args);
2
3builder.Services.AddControllersWithViews();
4builder.Services.AddAuthentication(IdentityConstants.ApplicationScheme)
5    .AddCookie(IdentityConstants.ApplicationScheme);
6builder.Services.AddAuthorization();
7
8var app = builder.Build();
9
10app.UseRouting();
11app.UseAuthentication();
12app.UseAuthorization();
13
14app.MapDefaultControllerRoute();
15app.Run();

Middleware order matters. UseAuthentication() must run before UseAuthorization(), otherwise the framework tries to apply access rules before the current user has been identified.

Separating concerns cleanly

A secure MVC application usually keeps these concerns separate:

  • credential validation and sign-in
  • user data storage
  • access rules for controllers and actions
  • claim or role assignment

That separation makes it easier to change one part without weakening another. For example, you can add external login providers without rewriting your controller authorization rules.

Common Pitfalls

The most serious mistake is confusing authentication with authorization. Many applications check whether a user is logged in and stop there, which means any authenticated user may reach admin-only actions. Add explicit role or policy checks anywhere privileges differ.

Another common issue is putting authorization rules only in the UI. Hiding a menu link does not protect the controller action. The backend must enforce access with [Authorize], roles, or policies.

Developers also get into trouble when they build their own password storage instead of using the platform identity stack. Password hashing, cookie expiry, account lockout, and reset flows are security-sensitive and easy to get wrong manually.

Finally, watch middleware order and anonymous endpoints. If an action should remain public, mark it intentionally with [AllowAnonymous] rather than relying on a missing attribute somewhere else in the controller hierarchy.

Summary

  • Authentication identifies the user; authorization decides which resources that user may access.
  • Use ASP.NET Identity or the framework authentication system instead of custom password handling.
  • Protect controllers and actions with [Authorize], roles, or policies.
  • Enforce access on the server, not just in the user interface.
  • Configure middleware in the correct order so request identity exists before authorization runs.

Course illustration
Course illustration

All Rights Reserved.