1

I have an API that is used in a multi-site/multi-location environment. At the moment, each user has roles defined but is locked to only one location. I am needing to extend this out to where a user may have admin roles for one location and then may be standard user at another location. They may also have no roles/no access to a bunch of locations.

Here is what I am working with right now (asp.net core 2.2):

public class ApplicationUser : IdentityUser
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int? LocationId { get; set; }
    public virtual Locations Locations { get; set; }
    public int? ContactPersonId { get; set; }
    public virtual ContactPerson ContactPerson { get; set; }
}

public class Locations
{
    public int Id { get; set; }
    public string Name { get; set; }

    public virtual ApplicationUser ApplicationUser { get; set; }
}

public class ContactPerson
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    public string UserId { get; set; }
    public virtual ApplicationUser ApplicationUser { get; set; }

    public virtual ICollection<ContactOrganizationPerson> ContactOrganizationPeople { get; set; }
    public virtual ICollection<ContactAddress> ContactAddresses { get; set; }
    public virtual ICollection<ContactPhone> ContactPhones { get; set; }
    public virtual ICollection<ContactEmail> ContactEmails { get; set; }

}

I am planning on changing the ApplicationUser to Locations table relationship to a Many to Many which would link the User to the Locations they are allowed to access. I have though about placing a payload in the M2M relationship table that would specify UserId, LocationId and Roles, but I would rather let Identity handle it if possible.

Is there a way to extend AspNetUserRoles so that I can specify a User to Role relationship for each location? Or is there a better way to accomplish this?

ThaKidd KG5ORD
  • 1,535
  • 3
  • 24
  • 38

1 Answers1

1

I'm not sure if this is going to help you, but I have extended .Net Core with functionality with IAuthorizationRequirement.

public class CustomRequirement : IAuthorizationRequirement
{
    public CustomRequirement ()
    {
    }
}

Create a new class

public class CustomHandler : AuthorizationHandler<CustomRequirement>

Override HandleRequirementAsync

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CustomRequirement requirement)

Here you can extract info about user from DB, compare, etc. If user is not allowed, return

return Task.CompletedTask;

If user is allowed, then use

context.Succeed(requirement);

Before returning. Then in your startup.cs:

services
            .AddAuthorization(options =>
            {
                options.AddPolicy("CustomPolicy", policy =>
                    policy.Requirements.Add(new CustomRequirement()));
            })

And then in your controllers you can add attribute

[Authorize(Policy = "CustomPolicy", Roles = "Admin")]

If requirement is not meet, user will get 401 unauthorized, which might not be what you want.