ASP.NET Identity User and Roles in Multisite [closed] - asp.net-mvc

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I am trying to create a permissions system in an ASP.NET MVC Application. I have been learning the newest Identity framework - here are my requirements:
A set of Hierarchical Roles for each set of functionality. So, for instance, there might be the following roles:
Inherit
Reader
Editor
Manager
Administrator
Each user would have one of those roles for each module (e.g. Events, Pages, etc.)
Users can be members of a security group. Each security group can be assigned a role directly and then all users in that group (who have not been explicitly assigned that permission) will inherit that role.
Multi-tenant site: each user has a set of sites which they are a member of. In the context of each site, they have a complete set of permissions which can be assigned by the site admin.
Through extending ASP.NET Identity, is it going to be possible for me to accomplish all of this? Or should I be building something custom from the ground-up?

9,999 times out of 10,000 implementing your own authentication system is the wrong way to go. Anything is easier than that, and it's a deceptively difficult thing to do right. ASP.NET Identity is actually pretty customizable, as it was created specifically for that purpose. You might need to do quite a bit to bootstrap your custom requirements fully, but it'll almost certainly be quicker and more secure using ASP.NET Identity.
UPDATE
UserManager's constructor takes an implementation of IUserStore. When working with Entity Framework, you typically just feed it Microsoft.AspNet.Identity.EntityFramework.UserStore, but this is your tie in point for extensibility. So, you can simply subclass UserStore and then override something like GetRolesAsync to do whatever custom role logic you need to implement. Then you'd just feed UserManager your subclass.

In version 1.0 of ASP.NET Membership, the IRole interface must have a string primary key. However in version 2.0, released March 2014, they added an IRole<TKey> that allows you to specify a role's primary key, as long as TKey implements IEquatable<TKey>.
That said, out of the box MVC integration points for authorization still depend on roles being ID'd by a single string. So if you are going to do authorization there, via attributes like Authorize, then you may need to write your own custom authorization attributes.
One way to achieve hierarchical roles would be to handle it in your application instead of in the model. I assume by hierarchical, you mean that Administrators have all the privileges of Managers, Managers have all the same privileges as Editors, and so on. You could achieve this by adding users to multiple roles, instead of having to walk through a modeled role hierarchy. Something like a db trigger could do it, but you can model it as a business rule in code too. Then if you restrict a page to Editor, Admins & Mgrs would have access to it as well.
Another way would be to just authorize certain actions for multiple roles:
[Authorize(Roles = "Administrator, Manager, Editor")]
public ActionResult Edit()
[Authorize(Roles = "Administrator, Manager")]
public ActionResult Manage()
[Authorize(Roles = "Administrator")]
public ActionResult Admin()
I disagree though that you would want to id roles on a composite key. If you want to protect MVC actions using the Authorize attribute, the ID of the role needs to be a constant value, like a string literal, int or Enum value, etc. If you keyed role on more than one of its properties, the number of properties you need to set on the attribute multiplies by the number of values in each component of the id. You would have Manager/SiteA, Manager/SiteB, and so on.
Instead, it sounds like it might be a good idea to just add properties to the gerund that tracks users in roles (the in-between table in a many-to-many relationship). To do this, you wouldn't be able to simply override and extend methods in the UserManager class as #Chris Pratt suggested. But that doesn't mean you have to throw out the baby with the bathwater. You can still use Microsoft.AspNet.Identity for authentication, and just write your own methods for role management, augmenting them to take an additional parameter:
AddToRoleAsync(TUser user, string roleName, string siteId);
public class Role : IRole<int>
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<UserInRole> Authorizes { get; set; }
}
public class UserInRole
{
public int RoleId { get; set; } // part of composite primary key
public int UserId { get; set; } // part of composite primary key
public string SiteId { get; set; } // part of composite primary key
public virtual Role Role { get; set; }
public virtual User User { get; set; }
}
public class User : IUser<int>
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<UserInRole> Authorized { get; set; }
}
Given the above, say your URL's look something like this:
/sites/site-a/admin
/sites/site-b/manage
/sites/site-c/edit
/sites/{siteId}/do
...you could write a custom authorization attribute that checks the URL and authorizes the principal both against the role name in the attribute and the siteId in the URL. To get access to the db from the attribute, if you are using IoC for EntityFramework, you can property inject an instance of your DbContext (or whatever interface you have wrapping it).

Following steps can solve your problem
Create granular level of roles...typically for each action
Group them up into GroupRoles...so that admin can easily manage it
Add individual level claims to user for specific permission
Some good examples of the same are below
http://www.3pillarglobal.com/insights/granular-level-user-and-role-management-using-asp-net-identity
http://bitoftech.net/2015/03/11/asp-net-identity-2-1-roles-based-authorization-authentication-asp-net-web-api/
Hope this solves your problem

Related

Extend ASP .NET Identity with custom List<property> and access it in the View

I am using ASP NET Identity 2.0. I need to extend the identity model with an ApplicationOrganization class (many-to-many with ApplicationUser).
So I created new class, ApplicationOrganization with;
public virtual ICollection<ApplicationUser> Users { get; set; }
public virtual ICollection<ApplicationOrganization> Organizations { get; set;}
to ApplicationUser class to create a many-to-many relationship.
I would like to add some combo (html select tag) with available organizations into _Layout.cshtml View. That's a problem for me. In the View I can accces current UserName, UserId or any other string property using Claims. But I don't know how to acces List of ApplicationOrganization connected to User in the View. I would like to avoid creating some new login Session. And I don't want to hit database in every view call.
No answer. Ok, one way I know now is I can serialize list as a string (xml, json or whatever) and store it as Identity claim. When I need it I can parse it back.

Users in Multiple Organizations with Different Roles

I'm fairly new to setting up security for websites and am having trouble finding the correct architecture/design/pattern/best practice for the type of authentication/authorization I am needing in a .NET MVC environment. I don't even know what to call it in order to do more research. Below is an example of what I need to implement. What is this called? (I don't think it's multi-tennant.)
Joe works inventory for a few stores in a Grocery Store chain. Joe is an Inventory Manager(can edit items) for Store A, but just an Inventory Clerk(only view items) for Store B and has no access to Store C.
So Joe should be able to access the ActionResult Edit in the InventoryController if he is trying to edit Store A, but should not be able to access the same ActionResult Edit if he is trying to edit Store B or C.
The straight-forward Identity or Claims based authorization isn't enough for this scenario (I don't think), but I don't know the "name" of the design I need in order to do further research. What is this design called?
It's called object-level authorization (aka object-level security, aka fine-grained authorization, etc.). Basically, permissions are based on "ownership" of objects, or perhaps better put in this scenario, being owned by an object. You would need to set up a many-to-many relationship between stores and employees, with payload of a role/grant. For example:
public class StoreEmployee
{
[Key, Column(Order = 1)]
[ForeignKey("Store")]
public int StoreId { get; set; }
public virtual Store Store { get; set; }
[Key, Column(Order = 2)]
[ForeignKey("Employee")]
public int EmployeeId { get; set; }
public virtual Employee Employee { get; set; }
public string Role { get; set; }
}
public class Store
{
...
public virtual ICollection<StoreEmployee> Employees { get; set; }
}
public class Employee
{
...
public virtual ICollection<StoreEmployee> Stores { get; set; }
}
With that, then you can use this relationship in your actions to verify whether a user has access:
if (!joe.Stores.Any(m => m.Store == storeA && m.Role == "Manager"))
{
return new HttpUnauthorizedResult();
}
Here, I kept things simple by just making Role a string. You could use a enum, or even an actual class that would also be persisted in your database. Or you could tie into the existing roles for users in general. It's up to you. You might also prefer to turn that into a custom action filter.
You could set this up as a multi tenant system. If every store is a tenant with its own user directory, then Joe would need to login to a different directory for store A then for store B and would get a another role assigned.
Joe would not be able to login to store C as he does not have an account in that directory.
If you want users to authenticate through a federated system, you'd need to set up a role per store and assign those based on which IdP the user came from.

MVC4 authentication & authorization for custom database

first of all I wanna say that I know there are many topics about this and I'm also searching the web to understand the whole concept that mvc deals with the security and keeping user information etc, but I wanted to get some advises, ideas from pros while I'm reading about this, so I'm gonna explain my situation and I'm thankful for the helps.
lets say I have a custom table called "Users"
public class Users : KySerializableObject
{
[required]
public virtual string Email { get; set; }
[required]
public virtual string userName {get; set; }
public virtual UserType UserType { get; set; }
[Required]
[ForeignKey("UserType")]
public virtual int UserTypeID { get; set; }
}
now what I know is that mvc provides a simpleMembership which works for a simple situations, but since I'm having different types of users and additional information for my User, what I'm wondering is how can I take a use of [authorize] tag for my user with different roles which I prefer to use my own roles table and also how can I deal with the login process ? I mean the part that I should use FormsAuthentication, or I'm not even sure I should use that or not, I'm really lost and I'd love to hear some advises from you guys. I'm not asking for codes or anything, any link to a good guidance that explains my situation would be awesome.
Thanks again
i have same situation and i am following a procedure for
Authentication FORMS Authentication
Authorization i write my own wrapper class to RoleProvider. with this you can directly use like
[Authorize (Rules = "Admin,Users")]
if your problem is authentication/authorization it will helps you perfectly.
Please take a look at this forum discussion in the ASP.Net forum
If you know your way around authentication, you should have nailed the code in here. But, for your requirement, please take a close look at this bit of code
string[] roles = //you add your custom roles for the current user to this string list
GenericPrincipal userPrincipal = new GenericPrincipal(new GenericIdentity(authTicket.Name),
roles);//then you create a Generic principle
Context.User = userPrinciple;
remember, if you are putting this code outside of Global.asax file, then Context is the HttpContext.Current
Now you can use [Authorize(Roles = "yourRole1, yourRole2")]
Hope that helps.

Good idea to resolve User roles in the application layer?

The reason I need a role-based system:
Restrict access to pages.
Restrict access to certain features on pages.
Check/validation inside service layer.
So I'm guessing, I can just create an enum and if I need a new role, just add it to the app code (the app would change anyways so requires a recompile).
So right now I have
public class User
{
/* .. */
public virtual ICollection<UserRole> Roles {get; set;}
}
public enum UserRoleType
{
Administrator,
User
}
public class UserRole
{
public int UserRoleId { get; set; }
public int RoleTypeValue { get; set; }
public UserRoleType RoleType
{
get { return (UserRoleType)RoleTypeValue; }
set { RoleTypeValue = (int)value; }
}
public virtual User User { get; set; }
}
This is a 1 to many. The pros I see for this is that instead of a many-many, there is a 1-many and joins are less. The application already knows what the role is based on what the int resolves the enum to.
Are there any flaws in the way Im doing this? Is there anything you have met in your experience that would require me to store the actual values in the database?
To be clear, you are suggesting that you don't need an actual lookup table in the database for Roles? Instead, they just have an int that is not a foreign key to anything--it is simply a representation of the enum in the application?
It's impossible to answer definitively without knowing all the details of your application. That disclaimer aside, I see nothing inherently problematic about it. It would certainly work fine for some systems.
Possible downsides:
There is no source of valid values enforced on the database side via referential integrity. What is to stop someone from entering "12452" for the RoleId in the database column? There are other ways around this like using check constraints, but they are not necessarily easier to maintain than a lookup table.
There is no way to effectively query the user/roles tables and have a human-readable representation of roles without knowing what the RoleIds represent (you will have to have the enum in front of you to make sense of the query result).
If the database is used for other applications, the roles will need to be represented (and maintained) in that application as well.

Alternative User management in ASP.NET MVC

I am in the planning phase of a new ASP.NET MVC application and one of the requirements is storing some user information that is not part of the standard set found in the User class that comes with ASP.NET MVC. I suppose it comes down to two questions.
1) Can I edit the class that is being used already to store the information that I need?
2) If I roll my own how can I keep things like the Authentication piece that make things so nice when trying to lock down some views using the User.IsAuthenticated method?
Another alternative I have considered is using the User class provided as is, and instead putting the other information into a separate table with the guid userid as the foreign key.
Suggestions?
Profiles are one option as #Burt says, and offers a lot of flexibility.
I had a similar need to track Employee information, but I opted to roll my own Employee class and create a relationship to a standard User. I really like how this has worked out as I can keep any Employee specific business logic separate from the User class Membership system.
Since not every User was going to be bound with an employee, this made more sense for my case. It may not for yours, but it is an alternative.
So, I have something like:
public class Employee
{
public Employee(string name) : this()
{
Name = name;
}
public virtual string Name { get; set; }
public virtual string Title { get; set; }
public virtual decimal Salary { get; set; }
public virtual decimal Hourly { get; set; }
public virtual decimal PerDiem { get; set; }
public virtual string StreetAddress { get; set; }
public virtual Guid UserId { get; set; }
public virtual MembershipUser User {
get
{
// note that I don't have a test for null in here,
// but should in a real case.
return Membership.GetUser(UserId);
}
}
}
See ASP.Net MVC Membership Starter Kit. It provides the Asp.Net MVC controllers, models, and views needed to administer users & roles. It will cut distance in half for you.
Out of the box, the starter kit gives you the following features:
List of Users
List of Roles
User
Account Info
Change Email Address
Change a User's Roles
Look into profiles that are part of the membership functionality provided by MS. They are extendable and pretty flexible.

Resources