The default ASP.NET Core 2 web template ships with a large amount of authentication code covering many scenarios: username/password login, external providers such as Google or Microsoft, two-factor authentication, and more.
You can use the template as-is, or if you only need cookie authentication, you can strip it down and build the sign-up and login pages yourself. As this post shows, cookie authentication is straightforward to set up.
#Register the authentication middleware
First, add the NuGet package Microsoft.AspNetCore.Authentication.Cookies. Then, you must configure and register the authentication middleware.
C#
public void ConfigureServices(IServiceCollection services)
{
services.AddAuthentication(options =>
{
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie();
services.AddMvc();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseAuthentication();
app.UseMvc();
}
You are now ready to use cookie authentication.
#Create the LogIn model
C#
public class LogInModel
{
[Required]
public string Username { get; set; }
[Required]
[DataType(DataType.Password)]
public string Password { get; set; }
public bool RememberMe { get; set; }
}
#Create the LogIn page
ASP.NET Core 2 introduced Razor Pages, which provide a simpler and more organized approach to building pages. You can also adapt this code to use a controller by moving the logic into a controller action.
Create a new page at Pages/login.cshtml. The page contains a form with username and password fields, styled with Bootstrap classes. A Razor Page must start with @page.
HTML
@page
<form method="post">
<div asp-validation-summary="All" class="text-danger"></div>
<div class="form-group">
<label asp-for="LogInModel.Username" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="LogInModel.Username" class="form-control" />
<span asp-validation-for="LogInModel.Username" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<label asp-for="LogInModel.Password" class="col-md-2 control-label"></label>
<div class="col-md-10">
<input asp-for="LogInModel.Password" class="form-control" />
<span asp-validation-for="LogInModel.Password" class="text-danger"></span>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<div class="checkbox">
<label asp-for="RememberMe">
<input asp-for="RememberMe" />
@Html.DisplayNameFor(m => m.RememberMe)
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Log In</button>
</div>
</div>
</form>
Next, add code to handle form submission. You can add it directly to the page or in a separate PageModel class. Since the code is short, it is added inline here.
HTML
@page
@using Microsoft.AspNetCore.Authentication;
@using Microsoft.AspNetCore.Authentication.Cookies;
@using System.Security.Claims;
@functions {
[BindProperty] // Bind on Post
public LogInModel LogInModel { get; set; }
public async Task<IActionResult> OnPostAsync()
{
if (ModelState.IsValid)
{
var isValid = true; // TODO Validate the username and the password with your own logic
if (!isValid)
{
ModelState.AddModelError("", "username or password is invalid");
return Page();
}
// Create the identity from the user info
var identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme, ClaimTypes.Name, ClaimTypes.Role);
identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, LogInModel.Username));
identity.AddClaim(new Claim(ClaimTypes.Name, LogInModel.Username));
// You can add roles to use role-based authorization
// identity.AddClaim(new Claim(ClaimTypes.Role, "Admin"));
// Authenticate using the identity
var principal = new ClaimsPrincipal(identity);
await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, principal, new AuthenticationProperties { IsPersistent = LogInModel.RememberMe });
return RedirectToPage("Index");
}
return Page();
}
}
<form>
...
</form>
The process is straightforward: create a ClaimsIdentity with the user's information and call HttpContext.SignInAsync(...) to issue the authentication cookie.
Now you can sign out using a single line of code:
C#
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
#Conclusion
Cookie authentication is simple to set up. If you do not need all the features provided by the default template, rolling your own sign-in and sign-up pages is a viable and lightweight alternative.
Do you have a question or a suggestion about this post? Contact me!