I've written a few complex MVC applications which are all role based and use .NET Membership. On my first project I used roles with structure similar to this:
Admin
Manager
Approver
I quickly discovered that wasn't very scalable, for example a customer would say "I want specific user x to have all manager privileges but not delete". I would then have to put a hack in the controller for that user.
Therefore, my second implementation led to this role structure:
CanCreate
CanDelete
CanEditAll
CanEditOwn
This approach then led to literally dozens of roles based on whether they could edit particular items globally or just their own etc. It also leads to a lot more controller actions and considerably more code - though maybe thats just the case in a complex application!
My question is, am I approaching this in the correct way, and are there any good online resources on the "correct" way to approach complex applications with loads of roles. Am I doing this correctly?
Indeed it's very interesting topic and I found myself struggling with the same problems as you do.
I read Derick Baileys interesting blog about that "Don’t Do Role-Based Authorization Checks; Do Activity-Based Checks" : http://lostechies.com/derickbailey/2011/05/24/dont-do-role-based-authorization-checks-do-activity-based-checks/
but had not time to experminet it myself.
A year on from this question I handle things a different way across projects. I'm now sticking to the classic roles of:
View
Edit
Delete
Add
BUT the action methods themselves return data like this:
var order = or.MyVisibleOrders().FirstOrDefault(x => x.Id == Id);
The logic for what is viewable and what is not is then handled by roles in the repository. The database will essentially never be queried for the restricted items in the first place.
Basic stuff but felt I should follow up on myself.
Related
I am hoping to create some secure areas of my MVC application, I understand how users can register, login etc with the out of the box views controllers etc.
One thing that seems to be lost on me is a way to manage these users after they register. Some things I would like to be able to do:
Assign roles to users
C-R-U-D users
C-R-U-D roles
Is this all functionality I have to build myself or am I just missing something here? Everything I have found lends itself to writing code to do all these things, but it seems as though these are standard enough that they should exist.
it's very simple. if you take a look at your auto-generated DB for users, you will see that it already contains tables for roles etc. so everything was already prepared for generic use, you just need to define the basics and use it.
You can first try to play with it a bit by adding values manually to the DB tables, just to get the feel of how it works.
define a role
assign users with that role
now depending on your use, whether you'd like to allow\block access to action or entire controllers just set this for example above a action or class [Authorize(Roles = "Admin")].
in addition to (3) you can also make decisions in the server side (C# and cshtml) according to the user roles, by using:
var userManager = new UserManager(userStore);
if(userManager.IsInRole(user.Id, "Admin")){...}
read more in this link, it goes over the CRUD actions - define and use.
I am using ASP.NET WebAPI with the built in authentication and identity services that come with the Visual Studio template. I now have it that a user can access the system and be authenticated.
The next logical step is to allow the user to create records. Lets say the user can have a "Project". How can I associate the user with a project at the point the project is created? It seems logical that the project table will just store the user_id provided by User.Identity.GetUserId().
Now, say that a project consists of Tasks. By default the WebAPI will create a Tasks controller, where I post a task. I think I would need to inject some additional information (such as the project id) at the point of creating the task.
But, say someone wants to add a task a project that doesn't belong to them. I need to verify this by loading the project, and checking the user_id field. Now I am adding two repositories to my controller. This seems like a lot of work.
Is it my own laziness that makes this seem hard???
I think this might be a related question, as it seems like you are looking for record-level authorization.
MVC / ASP.Net Best Practice for Record-Level Authorization
There is merit also in using multiple repositories. See here for an example of use.
http://www.asp.net/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application
Here, you would wrap the multiple repositories up within the UnitOfWork class.
I hope this points you in the right direction.
Let's say I have a ASP.NET MVC 4 application. I need to provide different privileges on different pages for same users. For example, The same user could be an administrator on one page and a guest on another. MVC by default provides system wide user privileges.
I dug up some information that I should use custom membership providers to achieve my goal, but am not yet sure about this.
Can someone suggest a solution?
The roles should behave the same on the same type of pages. Let's say that a topic's content, on a forum, could be edited only by the person who created it or by a moderator. Yet the user will not be able to edit someone else's topic and the moderator will not be able to edit a topic that is not a part of his topic subject group. The role system in my application should behave similarly.
You don't necessarily have to create a custom membership provider, but you are going to have to think about permissions differently.
To start, replace the word "Role" with "Operation" in your head.
You need to create atomic, fine grained permissions in your application such as:
UserPropertiesView
UserPropertiesModify
CreateUser
DeleteUser
RolesView
RolesModify
CreateRole
DeleteRole
It might be difficult at first, but this gives you great control and flexibility over assigning operations to individual users. Since different pages will have different operations, you will be able to customize their access.
Unfortunately, the out of the box ASP.Net membership and role providers all work off the concept of a course grained Role. So long as you know they are Operations, and not roles, you will be good.
Abstractions are your friend here:
public static class Permissions
{
public static bool Operation(string op)
{
//this class can be a lot better
// it can be testable, and check
// error conditions, but this is
// only an example :)
return HttpContext.Current.User.IsInRole(op);
}
}
Somewhere you will want to group all these operations up into Roles, but that will require some custom programming on your part.
Custom Providers really aren't that scary, and you can extend the built in ones easily.
Custom Role Provider
Custom Membership Provider
I'm creating a new ASP.NET MVC application. So far I've used the Account controller for actions related to a user's account -- Login/Logout, Activation (like Register, but I use Register for other actions in the site so I've renamed it), Add/Update Contact information. Up to now, though, I've been concentrating on the administrative user views.
I'm at the point where I'm going to start creating the various views that non-administrative users will see. These are rather limited compared to the administrative interface. My inclination is to create a new set of views and associated controller in the User "family" instead of using the Account views/controller. Is this a good idea or should I stick with the Account controller? My feeling is that since this is for ordinary users it should be a separate controller since Account would apply to both ordinary and administrative users.
EDIT: After reading the first couple of responses, my refactored question is:
Do you consider the Account controller to be for administrative actions related to the user's account or for all actions on the user's account? Would you distinguish between membership/role related views/data and application related views/data to the extent of creating a new controller.
Related, but doesn't directly answer my question: ASP.NET MVC Account Controller usage guidelines?
I don't think there's a right or wrong answer here, so I'll give you my opinion.
Technically, either solution (extending the Account controller or creating a new controller) will work just fine.
So I think this is more a question of how the users perceive the functionality. I think it's a good idea to follow the convention that the URI dictates the controller (or vice versa, if you prefer).
If, for example, you'd like to have the "administrative" actions on a separate path, then that should be a separate controller. You might want to do this, for example, if you use an IIS module for authentication or if it makes your log analysis easier.
On the other hand, it might be the case that the users perceive account functions and administrative functions as part of the same family of actions, except that some users have additional features. If so, then that suggests that should be on the same path in the URI and, hence, part of the same controller.
Summing up, I think this is a question you should ask your user representative instead of folks on this site. :)
Update: Regarding your updated question, I would say that it is fairly natural to put an action for changing a user's password on the Account controller, and that action could be invoked by the user herself, not just an administrator. So I wouldn't presume that the Account controller is strictly for administrative tasks. On the other hand, your example of the fund-raising performance is well outside of the scope of membership-related things, so it is not clear that it belongs on Account, either. I'm still leaning towards, "ask your user representative."
In ASP.NET MVC you will usually create controls based on data types rather than access types. For example:
Instead of 2 /Controllers/UsersControl.cs and /Controllers/Admin/UsersControls.cs it is easier to use one common controller for both admins and regular users - /Controllers/UsersController.cs (by setting different [Authorize] attributes and views).
I would keep existing AccountController.cs for encapsulating account related functionality. And just add new UsersController.cs for the rest Users related functionality (which could have methods like OnlineUsers etc.)
I'm new to ASP.NET MVC and all tutorials, samples, and the like I seem to find are very basic.
Is it possible (and if yes, a good design) to have routes like so:
.../Organization/10/User/5/Edit
.../Organization/10/User/List
In other words; can the urls mirror your domain model?
Possible, yes, with a route something like:
"~/Organization/{orgId}/{Controller}/{id}/{action}"
Whether it is a good design or not I couldn't say for sure, only that it seems rather complicated to me.
If you have multiple User tables, one for each company, it might make some sense.
Unless there is absolute necessity, keep routes decoupled from object model relations. Otherwise you will have to rewrite routes on every change in model.
"If you have multiple User tables, one for each company, it might make some sense."
Why only then?
"~/Organization/10/User/5/Edit"
... gives me the organization context at all times.
I didn't say so in my first question, but I've written an action filter that authorizes according to the rule that the logged on user must belong to the organization of the current action (hence not being able to see/edit/whatever user(s) of another organization).
I'm not saying that it's the best solution, but if not implementing this cross-cutting concern (aspect) as an action filter knowing the org id (via the action params), how would you solve the authorization issue elegantly?
As I initially stated, I'm new to the world of MVC and very excited about the answers.