I am building a .NET app and have based it (for now) on ASP.NET Identity as that seems to be to "correct" way to do things currently. While I have extensive programming experience, this is one of the first times I have had to deal with writing a login system from "scratch" as it were.
That being said, my application needs 3 user types, and I cannot for the life of me determine how to reflect this accurately in the Identity model, as the three have vastly different structures. For simplicity, we will call them User, Member, and Org Admin. An Org Admin has probably the most freedom aside from a sysadmin, as they have multiple Members nested underneath them and multiple Users they represent. A Member belongs to an Org and can see its Users, and each Member has responsibility for multiple Users. A User can be represented by many Orgs.
I thought about a login user that is extended to User and Member and then using RBAC to specify a member as the ORG Admin, but I am having trouble figuring determining a way to do this that doesn't make EF mad. I will fully admit I have never been great with EF and am better with Dapper etc.
I would appreciate any assistance with this.
I am building a .NET app and have based it (for now) on ASP.NET Identity as that seems to be to "correct" way to do things currently. While I have extensive programming experience, this is one of the first times I have had to deal with writing a login system from "scratch" as it were.
That being said, my application needs 3 user types, and I cannot for the life of me determine how to reflect this accurately in the Identity model, as the three have vastly different structures. For simplicity, we will call them User, Member, and Org Admin. An Org Admin has probably the most freedom aside from a sysadmin, as they have multiple Members nested underneath them and multiple Users they represent. A Member belongs to an Org and can see its Users, and each Member has responsibility for multiple Users. A User can be represented by many Orgs.
I thought about a login user that is extended to User and Member and then using RBAC to specify a member as the ORG Admin, but I am having trouble figuring determining a way to do this that doesn't make EF mad. I will fully admit I have never been great with EF and am better with Dapper etc.
I would appreciate any assistance with this.
Share Improve this question edited Jan 21 at 1:37 Rena 36.8k7 gold badges46 silver badges86 bronze badges asked Jan 18 at 0:25 JacrysJacrys 7151 gold badge7 silver badges22 bronze badges 2- What exactly have you tried so far? We're much more here to help with specific questions of the form "I tried X, but it did not do what I expect and instead resulted in an error!" accompanied by a Minimal, Complete, and Verifiable example – ti7 Commented Jan 18 at 0:27
- Identity is based on EFCore by default, you might meet much more trouble using dapper – Ruikai Feng Commented Jan 22 at 9:38
1 Answer
Reset to default 0consider user model as below:
public class AppUser : IdentityUser
{
public virtual List<AppUserOrg>? AppUserOrgs { get; set; }
}
public class Org
{
public int Id { get; set; }
public string? Name { get; set; }
public virtual List<AppUserOrg>? AppUserOrgs { get; set; }
}
public class AppUserOrg
{
public int Id { get;set; }
public string? UserType { get; set; }
public virtual AppUser AppUser { get; set; }
public string UserId { get; set; }
public virtual Org Org { get; set; }
public int OrgId { get;set; }
}
enable lazyloading for EFCore:
install the package:Microsoft.EntityFrameworkCore.Proxies
register identity related services:
builder.Services.AddDbContext<IdentityCusUserContext>(
options =>
{
options.UseSqlServer(connectionString);
options.UseLazyLoadingProxies();
});
builder.Services.AddDefaultIdentity<AppUser>(options => options.SignIn.RequireConfirmedAccount = true).AddEntityFrameworkStores<IdentityCusUserContext>();
add custom identity to userprinceple with IUserClaimsPrincipalFactory
public class CustomClaimsPrincipalFactory :
UserClaimsPrincipalFactory<AppUser>
{
public CustomClaimsPrincipalFactory(
UserManager<AppUser> userManager,
IOptions<IdentityOptions> optionsAccessor)
: base(userManager, optionsAccessor)
{
}
public async override Task<ClaimsPrincipal> CreateAsync(AppUser user)
{
var principal = await base.CreateAsync(user);
var appUserOrgs = user.AppUserOrgs;
foreach(var appUserOrg in appUserOrgs)
{
((ClaimsIdentity)principal.Identity).AddClaims(
new[] { new Claim("OrgRole", String.Format("{0}:{1}", appUserOrg.Org.Name,appUserOrg.UserType)) });
}
return principal;
}
}
Register it after other identity related services:
builder.Services.AddScoped<IUserClaimsPrincipalFactory<AppUser>,
CustomClaimsPrincipalFactory>();
with the data in db:
After you've login,you could see the claim:
Now you could set up policy based authorization follow the document with the OrgRole
claims above for your requirement