I am building an ASP.net MVC 4 application.
In the past I have used the [Authorize] attribute to authorize users according to their role(s).
However, I now need to a more flexible solution where role authorization can be changed by altering the database rather than changing the source code.
Can anyone recommend a suitable way to do this?
I have looked into overriding the OnAuthorize method but apparently this is not recommended due to issues with output caching.
You can do something like this, we have been using this in our application
[AttributeUsageAttribute
(AttributeTargets.Class | AttributeTargets.Struct |
AttributeTargets.Constructor | AttributeTargets.Method, Inherited = false)]
public class RequirePermissionsAttribute : ActionFilterAttribute, IAuthorizationFilter
{
// Use inbuilt methods
//OnAuthorization
//HandleUnauthorizedRequest
//OnCacheAuthorization
}
[RequirePermissions(PermissionItems.ViewThisPage)]
public ActionResult Index()
{
}
Not sure if I understood your requirement correctly, but you could have two levels of roles, with a data model something like:
User -in-> Role -has-> Permission
With m-n relationships between Users and Roles, and between Roles and Permissions.
If you do this, your permissions can be quite fine-grained and stable, while roles can be coarse-grained and flexibly mapped to sets of permissions.
One way to implement this is to simply write a custom RoleProvider that does the join Users-Roles-Permissions and returns the permissions as application roles.
If you do this, you can use the standard Authorize attribute, specifying one of your fine-grained permission names rather than a coarse-grained role name, e.g.:
[Authorize(Permissions.ViewCustomers)]
Related
often we attach role with action like below way
[Authorize(Roles = "Admin, SuperUser")]
[Authorize(Users="Jacquo, Steve", Roles="Admin, SuperUser")]
Users : Comma-separated list of usernames that are allowed to access the action method.
Roles : Comma-separated list of role names. To Access the action method, users must be in at least one of these roles.
[Authorize(Roles = "Producer")]
[Authorize(Roles = "Admin")]
public ActionResult Details(int id) {
// Only available to users who are Producers AND Editors
}
now see authorize and role name is hard coded with action method. suppose action Details is associated with admin role which is hard coded but how could i attach more role to details action or remove any role from details action at run time. i guess it is not possible because asp.net mvc not providing anything built in.
i search google to see that anyone does it anything such as what i am looking for. unfortunately found no similar write up.
so i need some guidance that how could i develop a UI from where admin can associate role with action instead of hard coding at development time.
so tell me your think how could i associate a role or multiple roles with action from a custom UI.
also tell me how could i check at run time that user has that role when user try to access a specific action.
please discuss in details for designing this part what i am looking for. still it is not clear to you what i am looking for then tell me i will try to explain the same in more details.
thanks
First: in every controller you should create a user object in controller constructor. like this:
public class MyController : Controller
{
ApplicationUser user;
public MyController ()
{
user = System.Web.HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>().FindById(System.Web.HttpContext.Current.User.Identity.GetUserId());
}
Then you could use user object anywhere in your controller methods.
"how could i develop a UI from where admin can associate role": in razor view use :
#if (User.IsInRole("Admin"))
{}
"how could i associate a role or multiple roles with action from a custom UI":
No need to that. When you create user in controller, you have access user all roles in controller methods.
"how could i check at run time that user has that role":
Use
if(user.IsInRole("Admin"))
I've got an architecture issue that I'm hoping someone can be of assistance to guide me in a more ideal strategy. The way I've been forced to do this reeks of "code smell".
I've got two different kinds of "Roles". I've got the built in Identity Roles, and I've got a custom set of roles (User Group Roles). I store these User Group Roles in a database, essentially a relationship between a user id, a usergroup role id, and a usergroup id. I'm using Ninject for dependency injection of my UserGroupService that handles all the CRUD operations of assigning users with certain usergroup roles to usergroups.
My first plan of attack was to create a custom authorization attribute that I could place on actions, similar to the Identity [Authorize(Role="")] attribute. I did not have any luck with this because I cannot inject a service into an attribute class (needs a parameterless constructor).
After that didn't work, my second plan of attack was to write an extension method for IPrincipal, essentially mimicking User.IsInRole("") with User.IsInUserGroupRole(""). This didn't work because I cannot inject a service into a static class.
Currently I am stuck including some booleans in the model of every view that has role based logic involved. So for instance:
public ActionResult Navigation()
{
var isSystemAdmin = User.IsInRole("Administrator");
var isUserGroupAdmin = _userGroupService.IsUserGroupAdmin(User.Identity.GetUserId()) && !isSystemAdmin;
var isGeneralUser = !isSystemAdmin && !isUserGroupAdmin;
var model = new NavigationViewModel
{
IsSystemAdmin = isSystemAdmin,
IsUserGroupAdmin = isUserGroupAdmin,
IsGeneralUser = isGeneralUser
};
return PartialView("_Navigation", model);
}
The issue here is that I have to do this any time I want to determine what kind of roles the user is currently in. It works, but it smells.
Am I missing something here? I think the most ideal option would be the extension method strategy of being able to call it right off of User, but cannot seem to make that work.
Constructor DI is not the only way to get access to a dependency.
Each IOC has a way of resolving a dependency, all you need is a reference to the IOC container. So, even if your attribute requires a parameterless constructor you could still resolve the dependency manually.
Something like this should help :
http://www.c-sharpcorner.com/UploadFile/47fc0a/resolving-dependency-using-ninject/
Is it a great way to use your IOC this way? Probably not but it sure beats what you're doing now.
I develop a web project. I use Asp.Net MVC, Entity Framework. I will have roles for users in admin panel. Usrs makes processes according to their roles. I want to use design patterns for this projects. Which type of a pattern do I use for this role authorisation? Any idea?
Thanks in advance.
Easiest way to implement role management is using ASP.NET membership provider.
You then have two ways of protecting actions based on roles.
If you want to ensure that only certain roles can execute an action method, you would use the Authorize attribute and define the list of allowed roles:
[Authorize(Roles = "Admin, Manager")]
public ActionResult AdministratorsOnly()
{
return View();
}
If you need to hide functionality on the views, you can use the User.IsInRole() method to check if the currently logged in user has that role:
if(User.IsInRole("Admin"))
{
Delete account
}
In my MVC application I have Player and Coach objects, and a user can be one or the other. I also have Team objects and what I want to know is how I prevent a user who is in a list of Players or is the Coach of a Team gaining access to a route like /Teams/Details/2 where 2 is the id of a team other than that which he/she is part of.
Thanks in advance!
Since you want to restrict an id that they aren't a part of, this seems like a situation where you can Inherit from the AuthorizeAttribute and provide your implementation for AuthorizeCore
Your implementation could check their role/team id and decide what to do / redirect.
public class TeamAuthorize : AuthorizeAttribute
{
protected override bool AuthorizeCore(HttpContextBase httpContext)
{
return UserIsInTeam(httpContext); //whatever code you are using to check if the team id is right
}
}
You can now apply it like any other attribute.
[TeamAuthorize]
The very simplest solution would be to change the URLs from using IDs to random GUIDs. You would almost eliminate the chance of someone guessing another valid value. Of course, this is not secure by definition (mostly because someone could get the other URL from history or another source), but in some scenarios this is enough.
A better solution is to create a new attribute based on IActionFilter interface that implements OnActionExecuting method and checks the ID by using this.ControllerContext.HttpContext.User.Identity.Name and this.RouteData.Values["id"]. You will then apply this attribute to your controller methods.
In our current system we implemented row level security in controller methods by just adding the code that verifies the user permissions as the first line in each method. The checking code is the same as with the attribute and it requires the same amount of code to add. This approach has one additional benefit - it is easier to implement scenarios like where a coach would be able to see the details of other teams but not modify them (we have one action and view for both reading and updating depending on permissions).
You would also use the last approach if you need to go to the database to check the permissions and you are using IoC frameworks such as Ninject with constructor based injection - since you will not have access to those values in the attribute.
I am creating website (football, soccer) in ASP.NET MVC3 and I want have users (with additional information then user in default membership, these are ordinary visitors) and players which I think it is best thet they would inherit users and have some addional iformation as dress number, ... Players also could post articles, users can just comment articles. What is best way to do this? Should I use default membership provider or should I make my own or use some 3rd party solutions? And can you post some articles and tutorials for changing original provider or article for making own provider for asp.net MVC3? Or is it same as MVC2?
It is very easy to create your own Membership Provider. Just create class derived from MembershipProvider. And implement members which look into DB, for example (or any other data source).
public class YourMembershipClass: MembershipProvider
{
public override bool ValidateUser(string username, string password)
{
return YourDataLayer.ValidateUser(username, password);
}
public override MembershipUser GetUser(object providerUserKey, bool userIsOnline)
{
return YourDataLayer.GetSpecificUser(providerUserKey, userIsOnline);
}
// Implement the other methods as well
}
Then add your YourMembershipClass to web.config:
<membership defaultProvider="MlgMembership">
<providers>
<clear />
<add name="CustomMembership" type="YourMembershipClass" enablePasswordRetrieval="false" />
</providers>
</membership>
If you are looking to store profile type information e.g. first name, last name, job title etc. against each user then you should be able to use the Profile system built into ASP.NET Membership. If you are looking to store more identity related information then yes you will have to create some sort of custom membership provider. There is a good video on creating a custom provider on the ASP.NET website: http://www.asp.net/general/videos/how-do-i-create-a-custom-membership-provider
Regarding allowing different types of users to perform different actions you can use the Roles system built into ASP.NET Membership. You can tell your action methods to only allow calls from users in certain roles. For example if you had a PostArticle action method and you only wanted players to be able to access it you would have something like this:
[Authorize(Roles="Player")]
public ActionResult PostArtcile(){
return View();
}
The Authorize attribute tells MVC to only allow authenticated users in the "Player" role to call the action method. You'll still need to restrict the availability of a post article link in your front end but there are several ways to do that.
There is a great series of articles by Scott Mitchell which covers all things membership based: https://web.archive.org/web/20211020202857/http://www.4guysfromrolla.com/articles/120705-1.aspx
Have a look at this soccer Club Site asp.net starter kit.
I Advice you to:
Use Membership provider to just deal
with user registration and
authentication. And let it take care of user security stuffs (rest password, validate user ....)
Then use Roles to separate your
users to their roles ("Players,
normalUsers,..").
And NEVER use Profile provider
cause it cost so many traffic you
don't want and instead of you could
make your custom table in DataBase to
store your additional information.
Then you may use EF or any ORM to get
this information whenever you want.
Don't forget to use authorization attributes [Authorize(Roles="Players")]in your Controllers and Actions deppending on the Roles.
I would advise implementing your own membership provider, it means implementing only the bits you need and forms a foundation for all your user management.
The Membership provider is the same for WebForms and MVC, there are quite a few examples on SO and Google.