10 - Identity
Choices in new project
- No Authentication
- No authentication/authorization
- Individual User Accounts
- Login info stored in app db – supports 3rd party logins – FB, Google, etc.
- Work or School Accounts
- Active directory
- Windows Authentication
- Intranet apps
Identity methods in code
Most of the initial setup is done by the middleware
- User.IsAuthenticated()
- User.IsInRole("rolename")
- User.GetDisplayName
- UserManager.GetUserName(User)
- SignInManager.IsSignedIn(User)
Identity Attributes
-
[Authorize] – controller or action method
- Only logged in users (redirect to login page)
-
[AllowAnonymous]
- Will always override [Authorize]
-
[Authorize(Roles="admin, sales")]
- Roles in single list are OR-ed
-
[Authorize(Roles="admin")] [Authorize(Roles="sales")] - Two or more attributes are AND-ed
SQL Injection and Resource probing
Identity does not protect against SQL injection / resource probing!!
.../foobars/1 vs .../foobars/27
Identity middleware options 1
services.Configure<IdentityOptions>(options => {
// Password settings
options.Password.RequireDigit = true;
options.Password.RequiredLength = 8;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = true;
options.Password.RequireLowercase = false;
options.Password.RequiredUniqueChars = 6;
// Lockout settings
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(30);
options.Lockout.MaxFailedAccessAttempts = 10;
options.Lockout.AllowedForNewUsers = true;
// User settings
options.User.RequireUniqueEmail = true;
});
Identity middleware options 2
services.ConfigureApplicationCookie(options => {
// Cookie settings
options.Cookie.HttpOnly = true;
options.ExpireTimeSpan = TimeSpan.FromMinutes(30);
// If the LoginPath isn't set, ASP.NET Core defaults
// the path to /Account/Login.
options.LoginPath = "/Account/Login";
// If the AccessDeniedPath isn't set, ASP.NET Core defaults
// the path to /Account/AccessDenied.
options.AccessDeniedPath = "/Account/AccessDenied";
options.SlidingExpiration = true;
});
Use configured middleware in Configure...
app.UseAuthentication();
app.UseAuthorization();
Identity - claims
- Identity is based on claims
- Collection of string keys and values
- Some keys are standardized
- Roles, user, user in role, etc. – abstractions constructed out of claims
Identity - Extending 1
- Default identity is based on IdentityUser and IdentityRole – both are using strings/guid as primary key.
- Default UI for identity is based on Razor pages, compiled into class library – not directly visible in code.
Identity - Extending 2
Add app specific user and role entities
namespace Domain.Identity
{
public class AppUser : IdentityUser<int> // PK type is int
{
// add relationships and data fields you need
}
public class AppRole : IdentityRole<int> // PK type is int
{
}
}
Identity - Extending 3 - AppDbContext
Derive your app DbContext from IdentityDbContext
namespace DAL.App.EF
{
// Force identity db context to use our AppUser and AppRole –
// with int as PK type
public class AppDbContext : IdentityDbContext<AppUser, AppRole, int>
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options)
{
}
// App DbSets
Identity – Configure startup
Use your AppDbContext and user/role
builder.Services.AddIdentity<Domain.App.Identity.AppUser, Domain.App.Identity.AppRole>(
options =>
options.SignIn.RequireConfirmedAccount = false)
.AddDefaultUI()
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
Don’t forget to update to AppUser in
/Views/Shared/_LoginPartial.cshtml
Identity – Custom UI (Extended AppUser)
-
Scaffold identity Razor pages into Web project
- Prerequired:
> dotnet tool install -g dotnet-aspnet-codegenerator
- Prerequired:
-
From inside Web project directory, run
> dotnet aspnet-codegenerator identity -dc DAL.App.EF.AppDbContext -f
-
Make no mistakes with DbContext name – new context and startup will be generated in case of mismatch! (it is CASE sensitive)
Identity – Custom UI
- Now you have full control over Identity in your Web project.
- Modify AppUser, AppRole – and update Razor pages when/where needed
- NB! There is no UI for role management – implement your own.
- Use:
RoleManager<AppRole>
_roleManager; - Similar to UserManager – add, create and modify roles.
- Roles are assigned to users via UserManager.