A Complete Guide - ASP.NET Core Authentication Mechanisms
Online Code run
Step-by-Step Guide: How to Implement ASP.NET Core Authentication Mechanisms
Introduction
Authentication is the process of verifying the identity of a user. ASP.NET Core offers several built-in mechanisms for user authentication, including cookie-based, JWT (JSON Web Tokens), OAuth, and others. This guide will cover the basics of implementing these mechanisms in ASP.NET Core.
Step 1: Setting Up an ASP.NET Core Project
First, create a new ASP.NET Core project. You can do this using Visual Studio or the .NET CLI.
Using Visual Studio:
- Open Visual Studio and create a new project.
- Choose "ASP.NET Core Web Application" and click "Next."
- Enter your project name and location, then click "Create."
- Select "Web Application (Model-View-Controller)" and click "Create."
Using .NET CLI:
dotnet new mvc -n AspNetAuthDemo
cd AspNetAuthDemo
Step 2: Cookie-Based Authentication
Cookie-based authentication is one of the simplest ways to authenticate users in ASP.NET Core.
Step 2.1: Configuring Cookie Authentication in Startup.cs
(or Program.cs
in .NET 6+)
In .NET 5 and earlier:
public class Startup
{ public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Account/Login"; // Redirect to login if not authenticated options.LogoutPath = "/Account/Logout"; // Redirect on logout options.AccessDeniedPath = "/Account/AccessDenied"; // Redirect on access denied }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); // Add Authentication Middleware app.UseAuthorization(); // Add Authorization Middleware app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); }
}
In .NET 6 and later:
var builder = WebApplication.CreateBuilder(args); // Add services to the container.
builder.Services.AddControllersWithViews(); builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(options => { options.LoginPath = "/Account/Login"; // Redirect to login if not authenticated options.LogoutPath = "/Account/Logout"; // Redirect on logout options.AccessDeniedPath = "/Account/AccessDenied"; // Redirect on access denied }); 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(); app.UseAuthentication(); // Add Authentication Middleware
app.UseAuthorization(); // Add Authorization Middleware app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
Step 2.2: Creating the Authentication Controllers and Views
Create an AccountController
with Login
, Logout
, and AccessDenied
actions.
public class AccountController : Controller
{ public IActionResult Login(string returnUrl) { ViewBag.ReturnUrl = returnUrl; return View(); } [HttpPost] [ValidateAntiForgeryToken] public async Task<IActionResult> Login(string username, string password, string returnUrl) { // Basic Authentication for demonstration purposes // In a real application, use a proper identity provider like ASP.NET Identity var isAuthenticated = username == "admin" && password == "password"; if (isAuthenticated) { var claims = new List<Claim> { new Claim(ClaimTypes.Name, username), new Claim(ClaimTypes.NameIdentifier, "1"), // User ID new Claim(ClaimTypes.Role, "Admin"), }; var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme); var authProperties = new AuthenticationProperties(); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProperties); return !string.IsNullOrWhiteSpace(returnUrl) ? RedirectToAction(returnUrl) : RedirectToAction("Index", "Home"); } ModelState.AddModelError(string.Empty, "Invalid Username/Password."); return View(); } public async Task<IActionResult> Logout() { await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme); return RedirectToAction("Index", "Home"); } public IActionResult AccessDenied() { return View(); }
}
Create corresponding views for Login
and AccessDenied
in the Views/Account
folder.
Login.cshtml
@model AspNetAuthDemo.Models.Account.LoginViewModel
@{ ViewBag.Title = "Login";
} <h2>Login</h2>
<form asp-action="Login" method="post"> <div asp-validation-summary="All"> </div> <div> <label asp-for="Username"></label> <input asp-for="Username" /> <span asp-validation-for="Username"></span> </div> <div> <label asp-for="Password"></label> <input asp-for="Password" type="password" /> <span asp-validation-for="Password"></span> </div> <input type="hidden" name="returnUrl" value="@ViewBag.ReturnUrl" /> <button type="submit">Login</button>
</form>
AccessDenied.cshtml
@{ ViewBag.Title = "Access Denied";
} <h2>Access Denied</h2>
<p>You do not have access to this resource.</p>
Step 2.3: Applying Authorization to Controllers or Actions
Restrict access to certain controllers or actions using the [Authorize]
attribute.
[Authorize]
public class AdminController : Controller
{ public IActionResult Index() { return View(); }
}
Step 3: JSON Web Tokens (JWT) Authentication
JWT authentication is a token-based security mechanism that enables you to authenticate API requests by sending a token with each request.
Step 3.1: Configuring JWT Authentication in Startup.cs
(or Program.cs
)
In .NET 5 and earlier:
public class Startup
{ public void ConfigureServices(IServiceCollection services) { services.AddControllers(); // Configure JWT authentication var key = Encoding.ASCII.GetBytes("your_secret_key"); // Secret key for signing JWTs services.AddAuthentication(options => { options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(options => { options.RequireHttpsMetadata = false; options.SaveToken = true; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(key), ValidateIssuer = false, ValidateAudience = false, }; }); services.AddAuthorization(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseRouting(); app.UseAuthentication(); // Add Authentication Middleware app.UseAuthorization(); // Add Authorization Middleware app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }
}
In .NET 6 and later:
var builder = WebApplication.CreateBuilder(args); // Add services to the container.
builder.Services.AddControllers(); // Configure JWT authentication
var key = Encoding.ASCII.GetBytes("your_secret_key"); // Secret key for signing JWTs builder.Services.AddAuthentication(options =>
{ options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(options =>
{ options.RequireHttpsMetadata = false; options.SaveToken = true; options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(key), ValidateIssuer = false, ValidateAudience = false, };
}); builder.Services.AddAuthorization(); var app = builder.Build(); // Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{ app.UseDeveloperExceptionPage();
} app.UseRouting(); app.UseAuthentication(); // Add Authentication Middleware
app.UseAuthorization(); // Add Authorization Middleware app.MapControllers(); app.Run();
Step 3.2: Creating the Authentication Controller
Create a TokenController
to issue JWTs.
[Route("api/[controller]")]
[ApiController]
public class TokenController : ControllerBase
{ private readonly IConfiguration _configuration; public TokenController(IConfiguration configuration) { _configuration = configuration; } [HttpPost("login")] public IActionResult Login([FromBody] LoginRequest request) { // Basic Authentication for demonstration purposes // In a real application, use a proper identity provider like ASP.NET Identity var isAuthenticated = request.Username == "admin" && request.Password == "password"; if (isAuthenticated) { var secrets = _configuration.GetSection("JwtSettings").Get<JwtSettings>(); var tokenHandler = new JwtSecurityTokenHandler(); var key = Encoding.ASCII.GetBytes(secrets.SecretKey); var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(new Claim[] { new Claim(ClaimTypes.Name, request.Username), new Claim(ClaimTypes.NameIdentifier, "1"), // User ID new Claim(ClaimTypes.Role, "Admin"), }), Expires = DateTime.UtcNow.AddHours(1), SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature), Issuer = secrets.Issuer, Audience = secrets.Audience, }; var token = tokenHandler.CreateToken(tokenDescriptor); var tokenString = tokenHandler.WriteToken(token); return Ok(new { Token = tokenString }); } return Unauthorized(); }
}
Define the JwtSettings
class.
public class JwtSettings
{ public string SecretKey { get; set; } public string Issuer { get; set; } public string Audience { get; set; }
}
Add JWT settings to your appsettings.json
file.
{ "JwtSettings": { "SecretKey": "your_secret_key", "Issuer": "your_domain.com", "Audience": "your_domain.com" }
}
Step 3.3: Applying Authorization to Controllers or Actions
Restrict access to certain controllers or actions using the [Authorize]
attribute.
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class AdminController : ControllerBase
{ [HttpGet] public IActionResult Index() { return Ok("Admin Data"); }
}
Step 3.4: Testing JWT Authentication
You can test the JWT authentication by sending a POST request to /api/token/login
with a JSON payload containing the username and password.
POST /api/token/login
Content-Type: application/json { "username": "admin", "password": "password"
}
The response will include a JWT token. Use this token in the Authorization
header for subsequent requests to protected resources.
GET /api/admin
Authorization: Bearer <your_jwt_token>
Step 4: OAuth and External Authentication Providers
OAuth is a protocol that allows applications to secure designated access to user accounts on an HTTP service.
Step 4.1: Configuring OAuth Authentication in Startup.cs
(or Program.cs
)
ASP.NET Core supports several popular OAuth providers out of the box, such as Google, Facebook, Twitter, and Microsoft. We'll use Google as an example.
In .NET 5 and earlier:
public class Startup
{ public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); services.AddAuthentication(options => { options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme; }) .AddCookie() .AddGoogle(options => { options.ClientId = "your_client_id"; options.ClientSecret = "your_client_secret"; }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseAuthentication(); // Add Authentication Middleware app.UseAuthorization(); // Add Authorization Middleware app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); }); }
}
In .NET 6 and later:
var builder = WebApplication.CreateBuilder(args); // Add services to the container.
builder.Services.AddControllersWithViews(); builder.Services.AddAuthentication(options =>
{ options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; options.DefaultChallengeScheme = GoogleDefaults.AuthenticationScheme;
})
.AddCookie()
.AddGoogle(options =>
{ options.ClientId = "your_client_id"; options.ClientSecret = "your_client_secret";
}); 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(); app.UseAuthentication(); // Add Authentication Middleware
app.UseAuthorization(); // Add Authorization Middleware app.MapControllerRoute( name: "default", pattern: "{controller=Home}/{action=Index}/{id?}"); app.Run();
Step 4.2: Creating the Authentication Link
Add a link in your Views/Shared/_Layout.cshtml
to allow users to log in using Google.
<!DOCTYPE html>
<html>
<head> <meta charset="utf-8" /> <title>@ViewBag.Title</title>
</head>
<body> <header> <h1>ASP.NET Core Authentication</h1> <a asp-controller="Account" asp-action="Login">Login</a> <a asp-controller="Account" asp-action="Logout">Logout</a> <a asp-area="" asp-controller="Account" asp-action="ExternalLogin" asp-route-provider="Google">Login with Google</a> </header> <main> @RenderBody() </main>
</body>
</html>
Add an ExternalLogin
action in the AccountController
.
public IActionResult ExternalLogin(string provider, string returnUrl = null)
{ var redirectUrl = Url.Action(nameof(ExternalLoginCallback), "Account", new { ReturnUrl = returnUrl }); var properties = _signInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl); return Challenge(properties, provider);
}
Step 4.3: Adding the Callback Endpoint
Add an ExternalLoginCallback
action in the AccountController
to handle the callback from the OAuth provider.
[HttpGet]
public async Task<IActionResult> ExternalLoginCallback(string returnUrl = null, string remoteError = null)
{ if (remoteError != null) { ModelState.AddModelError(string.Empty, $"Error from external provider: {remoteError}"); return View(nameof(Login)); } var info = await _signInManager.GetExternalLoginInfoAsync(); if (info == null) { ModelState.AddModelError(string.Empty, "Error loading external login information."); return View(nameof(Login)); } // Sign in the user with this external login provider if the user has an account var result = await _signInManager.ExternalLoginSignInAsync(info.LoginProvider, info.ProviderKey, isPersistent: false); if (result.Succeeded) { // Update any authentication tokens if necessary await _signInManager.UpdateExternalAuthenticationTokensAsync(info); return LocalRedirect(returnUrl); } if (result.IsLockedOut) { return View("Lockout"); } else { // If the user does not have an account, then ask the user to create an account. ViewData["ReturnUrl"] = returnUrl; ViewData["LoginProvider"] = info.LoginProvider; var email = info.Principal.FindFirstValue(ClaimTypes.Email); return View("ExternalLogin", new ExternalLoginViewModel { Email = email }); }
}
Step 4.4: Registering Your Application with Google
To use Google OAuth, you need to register your application in the Google Cloud Console.
- Go to the
You May Like This Related .NET Topic
Login to post a comment.