Now that ASP.NET Core has been out for a few years, I decided to start dabbling with it. Since I'm writing this for a personal app (to be running on my home machine) I decided I needed authentication, but wanted to make it simple. After some research I settled on this as the simplest approach to adding custom authentication to an ASP.NET Core webpage.
BTW, this has been testing against ASP.NET Core 2.2 & 3.1
Begin
Create a new ASP.NET Core project without any authentication.
Configure authentication
First , tell ASP.NET Core that we need authentication (via cookie authentication). In ConfigureServices() method of Startup class and enable authentication:
using Microsoft.AspNetCore.Authentication.Cookies; … public void ConfigureServices(IServiceCollection services) { // … // Enable cookie authentication services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme) .AddCookie(); }
In Configure() method of Startup class, add authentication to request processing pipeline:
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { // ... // Add authentication to request pipeline app.UseAuthentication(); }
Create a simple user model
First, for this application I created a simple CustomUser class:
public class CustomUser { public string Username { get; set; } public string Pwd { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public List<string> Roles = new List<string>(); }
Adding the Controller
Add a controller called AccountController with the following minimum functionality.
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.Cookies; using System.Security.Claims; ... public class AccountController : Controller { public AccountController() { } private CustomUser GetUserByUsername(string username) { // TODO: Replace this: CustomUser retValue = null; if (username == "Me") { retValue = new CustomUser() { Username = "Me", Pwd = "1", FirstName = "Myself", LastName = "AndI" }; retValue.Roles.Add("Admin"); } return retValue; } [HttpGet] public IActionResult Login() { return View(); } [HttpPost] public async Task<IActionResult> Login(string username, string password) { // Find and validate the user: CustomUser user = GetUserByUsername(username); if (user == null || user.Pwd != password) { ModelState.AddModelError("", "Incorrect username or password."); return View(); } // Create the identity var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme); identity.AddClaim(new Claim(ClaimTypes.Name, user.Username)); identity.AddClaim(new Claim(ClaimTypes.GivenName, user.FirstName)); identity.AddClaim(new Claim(ClaimTypes.Surname, user.LastName)); // Add roles foreach (var role in user.Roles) { identity.AddClaim(new Claim(ClaimTypes.Role, role)); } // Sign in var principal = new ClaimsPrincipal(identity); await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal); return RedirectToAction("Index", "Home"); } public async Task<IActionResult> Logout() { await HttpContext.SignOutAsync(); return RedirectToAction("Index", "Home"); } }
Create the Login view
Create the Login.cshtml view, located under "Views/Account" with the following content:
@{ ViewData["Title"] = "Login"; } <h1>Login</h1> <form asp-action="Login" method="post"> <div asp-validation-summary="ModelOnly" class="text-danger"></div> Username: <input name="username" /><br /> Password: <input type="password" name="password" /><br /> <input type="submit" /> </form>
Display either the username or login link
On either the Index.cshmtl or the layout page, add the following code:
@if (User.Identity.IsAuthenticated) { <div > Hello @User.Identity.Name </div> <div> <a href="http://bushconsulting.com/Account/Logout">Logout</a> </div> } else { <a href="http://bushconsulting.com/Account/Login">Login</a> }
Notice that the “User” instance (ClaimsPrincipal) is available within the page. It’s also available in the Controller.
And that’s all. Happy coding...
Next up: Hosting ASP.NET Core