1

I've done some searching but it doesn't look like a very commonly-asked or answered question. I need to implement a custom group authorization policy in an MVC application I am developing. It sort of follows the "classic" example:

Group

A user can create a group. A group exists as an object in a database with an Id, Name, and, among other things, a List of Users who belong to this group.

Role

A user can hold a role in many groups. For example, the creator of the group instantly becomes the administrator of the group. Different roles can access different things within the group.

I know it's very easy with pre-defined groups, but what about when I want to make the groups dynamic and each group be an object in the database?

A simple example of this in the real world would be groups on facebook, which have Admins, moderators, content-creators, etc. And only members can see them, edit them, or post to them.

Any ideas?

AllFallD0wn
  • 551
  • 7
  • 23

2 Answers2

1

This is a very subjective design question and there is probably no single "right" answer.

I tend to use the aspnet Roles for application-level roles, like for Sysadmins and normal users and has to do with application-level permissions - ability to add new users to the application, ability to delete records, ability to edit records, etc.

It sounds to me more like this is something you want users to be able to do themselves without oversight.

Create a Groups table, and have a many to many relationship with a Users table that defines which groups users are a part of.

If you only want 1 admin per group, you could make the Group table have an AdminUserId column. Otherwise have a many-to-many relationship table, GroupAdmins (I'd go for this option as it allows extensibility).

user1666620
  • 4,800
  • 18
  • 27
  • Yeah, I've got as far as making the group and the roles will be staying the same (Admin, Moderator, Member), but I wondered whether there was anything I could override/implement that would make "if (!IsAMember(user)) then return 401" easier, like the [Authorize(Group=id, Role=admin)] attribute – AllFallD0wn Sep 09 '15 at 14:59
  • @AllFallD0wn so your real question is how to add an attribute to an actionmethod which checks if a user is associated with a record? – user1666620 Sep 09 '15 at 15:02
  • It's "what is the best/cleanest way to implement this?" I'm assuming an attribute is probably the cleanest way as it avoids a lot of random calls and returns at the top of methods – AllFallD0wn Sep 09 '15 at 15:04
  • @AllFallD0wn "what is the best/cleanest way to implement this?" could refer to absolutely anything. – user1666620 Sep 09 '15 at 15:07
1

You could inherit AuthorizeAttribute to create any security scheme you like. But since you said it is not about authorization I am not sure if that is the right approach.

The AuthorizeAttribute does 2 different things:

  1. Checks if the current user can access the current controller/action.
  2. Executes a handler to take an action when they are not authorized.

Both of these things can be customized by subclassing AuthorizeAttribute. It is unclear from your question what action is supposed to be taken if the user doesn't belong in a Group or Role.

In any case, the best option for cross-cutting concerns (which this appears to be) is to implement either IActionFilter or IAuthorizationFilter (which is implemented by AuthorizeAttribute).

NOTE: Microsoft hasn't implemented this feature very well (or at least they tend to favor ActionFilterAttribute in their marketing, which are attributes that have behavior) for those of us using dependency injection. See passive attributes for the best option if you happen to be using DI in your application. See a couple of examples here and here.

Community
  • 1
  • 1
NightOwl888
  • 55,572
  • 24
  • 139
  • 212