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://www.bushconsulting.com/Account/Logout">Logout</a>
</div>
}
else
{
<a href="http://www.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