Skip to content

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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...

1
2
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
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

1
2
3
4
5
6
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
  • 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 _roleManager;
  • Similar to UserManager – add, create and modify roles.
  • Roles are assigned to users via UserManager.