Search code examples
c#asp.net-coreasp.net-identityn-tier-architecturemulti-tier

Multitier architecture and Identity. Why to use UserManager and RoleManager?


Microsoft Identity introduces UserManager<T> and RoleManager<T> classes to interact with AspNetUsers, AspNetRoles and the other database tables. But why we should use them? Maybe it is a better solution to scaffold the database and work with its tables directly using the Entity Framework and forget about classes UserManager<T> and RoleManager<T>?

Why am I asking?

I my application I want to follow the multitier architecture. I started with creating the DTO-class for the user:

public class UserDto
{
    public string Id { get; set; }
    public string UserName { get; set; }
    ...
    public List<RoleDto> Roles { get; set; }
}
public class RoleDto
{
    public string Id { get; set; }
    public string Name { get; set; }
    ...
}

Type IdentityUser I want to map into UserDto, type IdentityRole - into RoleDto.
As you can see, in UserDto I want to store roles of a user.
Now let's have a look at the IdentityUser type: link. It contains a lot of properties, but it doesn't have roles of the user.
So, when mapping IdentityUser into the UserDto, I need to work with RoleManager<T> to get roles of the user. I think, it's a dirty solution.

My idea

We can forget about UserManager<T> and RoleManager<T> types. We can simply scaffold the database and work with it using the Entity Framework.
After scaffolding of database I have the following:

public partial class AspNetUser
{
    public string Id { get; set; }
    public string UserName { get; set; }
    public string NormalizedUserName { get; set; }
    public string Email { get; set; }
    public string NormalizedEmail { get; set; }
    public bool EmailConfirmed { get; set; }
    public string PasswordHash { get; set; }
    public string SecurityStamp { get; set; }
    public string ConcurrencyStamp { get; set; }
    public string PhoneNumber { get; set; }
    public bool PhoneNumberConfirmed { get; set; }
    public bool TwoFactorEnabled { get; set; }
    public DateTimeOffset? LockoutEnd { get; set; }
    public bool LockoutEnabled { get; set; }
    public int AccessFailedCount { get; set; }

    public virtual ICollection<AspNetUserClaim> AspNetUserClaims { get; set; }
    public virtual ICollection<AspNetUserLogin> AspNetUserLogins { get; set; }
    public virtual ICollection<AspNetUserRole> AspNetUserRoles { get; set; }
    public virtual ICollection<AspNetUserToken> AspNetUserTokens { get; set; }
}
// AspNetUserClaim, AspNetUserLogin, AspNetUserRole and AspNetUserToken

I introduced only AspNetUser class to be short. As you can see, it has a property AspNetUserRoles - roles of the user. It's great, because now it's really simple to map this class into the UserDto.

Question

Is it a good idea to scaffold the database and don't work with UserManager and RoleManager classes? Maybe you can introduce a better solution?


Solution

  • Why do you think that this is a good idea? What would you gain by re-writing something like identity?

    From the Introduction to Identity on ASP.NET Core

    ASP.NET Core Identity:

    • Is an API that supports user interface (UI) login functionality.

    • Manages users, passwords, profile data, roles, claims, tokens, email confirmation, and more.

    It's not just database access. It is also code that manages login functionality, secure token creation, secure password management and much more.

    You need to take all of the above into consideration if you create a custom system, have an external auditor to pen-test your solution (even though this is a good idea whatever choice you make), unit test, performance test etc.

    All the above is already done. You can easily customize the identity with various hook points too.

    BTW, identity uses ef to access the datastore already by default.

    Do structure your multilayer application, but leave identity out of it. It is a horizontal concern and it's presence is there to simplify your development and let you worry about your business needs only.