There are plenty of questions (and information) on setting up asp.net membership, role providers and the like. Whether or not you should use the built in platform provided by microsoft, or role extend the base classes and role your own.
I have decided to extend the default providers and implement my own membership and role providers. Now my question, is specifically around role authentication.
Traditionally, you would create roles maybe like 'Manager, Administrator, Employee, Super User' or whatever you have. But what would/should you do with respect to permissions which I consider to be a finer grain of control? Let me elaborate....
Within my asp.net mvc site I have different areas like administration, management, messaging, reporting etc. I would crate roles for each of these like 'Administrator', 'Manager', 'Reporter' etc. Without the appropriate role, you can't gain access to that area of the site. So I would lock down the entire controllers with this at the class level.
But now take one area as an example; messaging, and say I wanted to have finer grain permissions for CRUD; create a message, view/read messages, edit messages, delete messages etc.
Finally my question. How would it be best to implement this finer grain of control? One approach I see (not sure if it is a good one), is to just create asp.net membership roles for everything. So I might have....
Messenger (broad level role), CreateMessage, ReadMessage, EditMessage, DeleteMessage.
On one hand I would like some users to be able to read/view messages. But not necessarily create or delete them. Individual controller actions could have the specific roles applied.
Do you see any problems with this approach? Do you have a better idea?
Solution So Far
I have decided to create my own schema and implement custom membership and role providers. My schema includes;
- User
- UserProfile
- Permission
- PermissionAssignment
- Role
- RoleAssignment
Going to be away for the next day or two but will update with more information when I get a chance.
I think you should forget about roles on the authorization mechanism, ask for permissions instead (at the end a role is an agrupation of permissions), so if you look it that way, your Authorize
Attribute should ask for an entity and action, not for a particular role. Something like:
[Authorize(Entities.Message, Actions.Create)]
public ActionResult CreateMessage()
[Authorize(Entities.Message, Actions.Edit)]
public ActionResult EditMessage()
[Authorize(Entities.Message, Actions.View)]
public ActionResult ViewMessage()
That way your roles do what they do best, abstract permissions collection instead of determining a inflexible way of access level.
EDIT: To handle specific rules like the one pointed by David Robbins, Manager A is not allowed to delete messages created by Manager B, assuming they both have the required permission to access this Controller Action, the Authorize is not responsible to check this type of rules, and even if you try to check that at Action Filter level it will be a pain, so what you can do is extend the Authorize validation to the ActionResult (injecting an action parameter holding the validation result), and let the ActionResult make the logic decision there with all the arguments in place.
This is a similar question, is not exactly the case pointed out here, but its a good starting point on extending the Authorize validation with Action Parameters.
With respect to your CRUD example, aren't you really talking about authorization, and would the authorization vary between the membership roles "Manager" and "Reporter"? I think you need to create a separate mechanism for those finer grained activities if the roles do not distinguish between a read and write authorization between messages.
If you were to create a role for each action - EditMessage, DeleteMessage - what will you do in the case when Manager A should NOT be able to delete messages for Manager B?
As well as adding [Authorize(Roles="Administrator")]
etc above your controller. You can also put that attribute on the indiviual Actions too