Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Duplicate Role Names on Asp.Net Identity and Multi-tenancy

I'm developing a Multi-tenancy web application with ASP.Net MVC and Identity 2.0. I have extended the IdentityRole like this:

public class ApplicationRole : IdentityRole
{
    public ApplicationRole() : base() { }
    public ApplicationRole(string name) : base(name) { }

    public string TenantId { get; set; }
}

This because each Tenant will have individual sets of roles, like "Admin", "Staff", etc.

But the problem is, when I add a new Role, if the "Tenant A" has "Admin" role, when I add to "Tenant B" the "Admin" role, I get an IdentityResult error because "Admin" name is taken... Its is kinda obvious because the "Name" field on the AspNetRoles table is Unique...

IdentityResult roleResult = await RoleManager.CreateAsync(
  new ApplicationRole
  {
    Name = "Admin",
    TenantId = GetTenantId()
  });

But then how I can customize ASP.Net Identity so the "Name" field in the "AspNetRoles" can be unique with "TenantId", and not alone? I found info about extend the IdentityRole (like I did adding a field), but not about change it or replace it...

like image 771
Click Ok Avatar asked Jan 23 '17 06:01

Click Ok


1 Answers

Simply alter database's schema on ApplicationDbContext's OnModelCreating method like this:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
    base.OnModelCreating(modelBuilder);

    var role = modelBuilder.Entity<IdentityRole>()
        .ToTable("AspNetRoles");
    role.Property(r => r.Name)
        .IsRequired()
        .HasMaxLength(256)
        .HasColumnAnnotation("Index", new IndexAnnotation(
            new IndexAttribute("RoleNameIndex") 
            { IsUnique = false }));
}

But you must customize RoleValidator class also. Because default role validator invalidates duplicated role names.

public class MyRoleValidator:RoleValidator<ApplicationRole>
{
     public override async Task<IdentityResult> ValidateAsync(ApplicationRole item)
     {
         // implement your validation logic here

         return IdentityResult.Success;
     }
}

Now every time you create the role manager you must set the role validator.

roleManager.RoleValidator=new MyRoleValidator();
like image 116
Sam FarajpourGhamari Avatar answered Oct 26 '22 04:10

Sam FarajpourGhamari