Overview
• Architecture
• Setup
• Scenarios• Registration
• Signin
• Signout
• User management
ASP.NET Identity library features
• Authenticate users• Identification (e.g. username,
certificate, facebook login)
• Store user information• Profile data (e.g. first & last name)
• Roles (Sales, Manager, Customer, etc.)
• Manage cookies• Using cookie authentication
middleware
ASP.NET Identity Architecture
• User models data
• User Store stores/retrieves user data in database
• User Manager manages security operations for user
User Manager
app
User
database
User Store
Setup
• NuGets
• Modeling users and database
• API for security features
• Configuration in DI
• Database setup
NuGets
Modeling users
• Define User class• Models user data for authentication and identity
• Derive from EF-provided IdentityUser base• Provides several properties/collections to manage identity data
• Add any custom properties needed• Will map to columns in a relational database table
public class MyUser : IdentityUser{
public string FirstName { get; set; }public string LastName { get; set; }
}
Modeling database
• IdentityDbContext class provides EF modeling of database tables
• Sometimes custom IdentityDbContext-derived class useful• Allows for schema modification
• Allows for custom tables, if needed
public class MyUserDatabase : IdentityDbContext<MyUser>{
public MyUserDatabase(DbContextOptions options) : base(options){}
}
Accessing security features
• UserManager provides main API for features• Creating, Deleting
• User lookup/query APIs
• Credential validation and lockout
• Managing/updating identity data
• Email/phone verification
• Custom UserManager-derived class sometimes used
Configuration with DI
• Many services used to provide identity• Typically registered in DI
• AddIdentity adds to ASP.NET Core DI system• Typical options callback delegate used to customize
• Extension methods for registering custom implementations
services.AddDbContext<MyUserDatabase>(options=>{
options.UseSqlServer("server=localhost;database=test;trusted_connection=yes;");});
services.AddIdentity<MyUser, IdentityRole>().AddUserManager<MyUserManager>().AddEntityFrameworkStores<MyUserDatabase>();
Database setup
• Migrations used to define DB schema
• EF tooling used to create database
Basic scenarios
• User creation
• Sign-in
• Sign-out
• User data management
User creation
• Decide on a provisioning process• Self-service registration
• Batch user import
• UserManager.CreateUser to create new user• Accepts new user and password as
parameters
Sign-in features and steps
• Login page must:• Validate credentials
• Issue claims into cookie
• Brute force prevention
Validate credentials
• UserManager.CheckPassword used to validate credentials
• Separate APIs for:• Creating claims
• Issuing cookies
• Brute force prevention
var user = await _userManager.FindByEmailAsync(model.Email);if (user != null){
if (await _userManager.CheckPasswordAsync(user, model.Password)){
// success!}
}
Claims and cookies
• Claims used to model user identity • Simple key/value pairs for ease to model identity
• Simple/portable for serialization into cookie
• Use cookie authentication middleware to manage cookie
var claims = new Claim[]{
new Claim("userId", user.Id)};var ci = new ClaimsIdentity(claims, "password");var cp = new ClaimsPrincipal(ci);
await HttpContext.Authentication.SignInAsync("Cookies", cp);
UserClaimsPrincipalFactory
• Helper class to encapsulate conversion of user to claims• Automatically maps basic properties, claims, and roles
• Claim types options can be used to configure claim types used
• Does not handle custom properties• Custom implementation necessary for this
Brute force prevention
• Must coordinate with UserManager for lockout• AccessFailedAsync used when password fails
• ResetAccessFailedCountAsync when password succeeds
• IsLockedOutAsync to check if user already locked out
SigninManager
• Helper class to encapsulate all of manual work• Does claims mapping
• Issues cookie
• Does brute force checking
var result = await _signinManager.PasswordSignInAsync(model.Email, model.Password, false, true);
if (result.Succeeded){
return Redirect("~/");}
Sign-out
• Simply clear authentication cookie• Or can use SigninManager
[HttpPost][ValidateAntiForgeryToken]public async Task<IActionResult> Logout(){
await HttpContext.Authentication.SignOutAsync("Cookies");
return Redirect("~/");}
User management
• Change password
• Profile
• Claims
• Roles
Change password
• UserManager provides ChangePassword API• Also, ChangeEmail and ChangeUsername
var user = await _userManager.GetUserAsync(User);
var result = await _userManager.ChangePasswordAsync(user,model.OldPassword, model.NewPassword);
if (result.Succeeded){
return View("ChangePasswordSuccess");}
Profile
• Custom user properties persisted with UserManager.Update• Might need to re-issue cookie with updated claims
var user = await _userManager.GetUserAsync(User);
user.FirstName = model.First;user.LastName = model.Last;
var result = await _userManager.UpdateAsync(user);if (result.Succeeded){
await _signinManager.SignInAsync(user, false);return View("ProfileSuccess");
}
Claims
• Claims allow for flexible user attributes• Key/value pairs
• AddClaim(s) and RemoveClaim(s) APIs to manage• Must explicitly manage duplicates
Roles
• Roles are special cased• Roles are just claims, so AddClaim API could be sufficient
• Role definition must exist to put user in role• Using the RoleManager
• Roles themselves can have claims• Use with caution
Summary
• ASP.NET identity is decent framework for managing user identity
• You must still understand what it’s doing for you
• Encapsulation layer would be recommended to control features