Asp.Net Core Authentication Mechanisms Complete Guide
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 Google Cloud Console.
- Create a new project.
- Navigate to "APIs & Services" > "Credentials."
- Click "Create Credentials" > "OAuth client ID."
- Configure your application type, name, and redirect URI (
http://localhost:5000/signin-google
for local development). - Copy the client ID and client secret and add them to your
Startup.cs
orProgram.cs
.
Login to post a comment.