In my MVC3 application I have ASP.NET Membership roles like - Manager, System Admin and Editor
I am using Windows Authentication for the website and I am adding the users in the Network to the Membership just like in the following example -
http://weblogs.asp.net/scottgu/pages/Recipe_3A00_-Implementing-Role_2D00_Based-Security-with-ASP.NET-2.0-using-Windows-Authentication-and-SQL-Server.aspx
But, my problem is there are people who require multiple permissions. For example
User-John is the Manager of Department-ABC and he can see all the Actions in Department-ABC.
User-John is also Editor in Department-XYZ and he should be able to see all the Actions of an Editor in Department-XYZ;
but NOT the Actions of Manager; because he is not the Manager of Department-XYZ.
User Mathew is the Manager of Department-XYZ and he is an Editor in Department-ABC.
If I use normal role privileges, it will allow User-John to be the Manager of both departments and it is not right.
My solution is to store the DepartmentID, UserID and RoleID in a seperate table in SQL database and allow according to this table.
How can I get the role ID from ASP.NET Membership in C# and also in SQL?
Is it safe to do?
Is there a better solution?
Activity based membership would probably fit here.
In activity based membership your users get access to actions, not to roles.
Typical usage is:
One action = one activity
There are still roles given to users, but they are used to group activities
There is n..n relation between roles and activities
Activity is just a custom action filter that is applied to the action.
Typical example is here (although I don't like this approach, so I made my own implementation).
[Activity(Name="DoSomething")]
public ActionResult DoSomething()
{
...
return View();
}
Membership can be stored in ASP Membership database table, custom table or represented as AD group. Depends whether you implement custom membership provider or you use default implementation.
At the end, there has to be n..n relationship like RoleActivity, where you link the particular role to the activity (like Manager1 to both AddMemberToDepartment and AddComment, and Manager2 to just AddComment). This relation can be classic n..n database relation or 'virtual', where role is in AD and database table relates to it only via group name.
EDIT:
If you use default database role based authorization, table aspnet_Roles will be generated for you. To support activity based membership you will have to add your own activity table manualy, along with additional role-activity relation.
This schema should help you proceed.
aspnet_Roles (autogenerated)
* ApplicationId
* RoleId
* ...(other autogenerated columns)...
aspnet_MyActivity (add manually)
* ActivityId
* ApplicationId
* Name
* Description
aspnet_MyPermission (add manually)
* ApplicationId
* RoleId
* ActivityId
You can fill roles using membership provider.
Then fill manually your activities as your application needs them, say, one activity per action method.
Finally, manually add your activity permissions to roles.
Real world scenario
If your organization is small enough, it may be acceptable to add one role per department and one activity per action/deparment:
role: Dep. mgr. of ABC,
role: Dep. mgr. of XYZ,
activity: createAbcUser,
activity: createXyzUser
Connect them using appropriate permissions and you have your requirement covered.
However, for a large number of departments adding one role per department and giving activity permission for each of them can be a little awkward. In that case you should stick with simple role "Department manager" and simple activity "Create user", and give your manager permission to create user. However, you have to stop manager to create user in a different department - use your hierarchy for that, meaning, check if your user belongs to your manager.
Your action filter will then look like this:
check if any of current users roles has a permission to run that activity
check your hierarchy: does your current user have a permission to work on referenced user?
If both of these are true, action method can be executed.
NOTE: You will probably reference user by some input parameter, so your action filter has to access that parameter. See Getting the values of action parameters within an action filter to solve that.
Related
I am building a SaaS application using ASP.NET MVC 5, where I need to store two different types of users who will have different field information to be stored for each. There will be Subscibers and General Users, where every General user will belong to a Subscriber. So, every user will have a parent subscriber.
Should I have a single ASPNETUSERS table to store all the users (subscriber / general users) with custom columns stored for each within the same table? I believe there has to be a better practice to achieve this. Since this will be a SaaS application where we are storing user information across multiple entities in a single database, what kind of database design should we go for?
For reference, here is the database design I have for the moment -
id [primary key of the user]
email
password
sub_name [subscriber name. will be populated only if the user is a subscriber]
sub_address [subscriber address, will be populated only if the user is a subscriber]
status [Stores if the user is active]
parent_id [Id of the parent. This will be populated only if the user is a General User]
Apart from the above, we will be registering the role of every user (Subscriber/General User)
Please advise. Thank you for your help.
You should use a single table and create two classes in your code for the different types of users. The ASP tables with entity framework use table per hierarchy (given away by the discriminator column):
public class Subscriber : IdentityUser {
public virtual List<GeneralUser> GeneralUsers {get; set;}
//other properties
}
and then create your general users:
public class GeneralUser : IdentityUser {
public virtual Subscriber Subs {get; set;}
//other properties
}
I've tried searching this for days and can't seem to find an adequate answer so I'll ask here.
I'm building an asp.net Membership website.
What I want to do is:
Allow a user to create an account - say UserA
I then want to allow UserA to create "sub accounts" tied into his account, but with different roles as well as different login names (I'll be using email address as the login name)
UserA would be the account admin of sorts.
UserA's sub accounts would be less "adminish" than UserA, but any data that they write to my DB (Entity Framework) would still be tied to the main UserA account which will be referenced to my tables via Membership.GetUser() API calls.
So 2 questions:
1) How would I reference the Membership tables in my EntityDataModel using DB First (I already ran the aspnet_regsql.exe)
2) How would I need to go about allowing UserA to create his own sub users?
Here's an image of my custom tables:
[MasterAccountUser]
MasterAccountId = aspnet_Membership.UserId
AccountNumber = autoincrement number
[UserAccount] - subaccount of [MasterUserAccount]
AccountId = aspnet_Membership.UserId (if I have to have each user create their own)
MasterAccountId = aspnet_Membership.UserId (but the same one as the [MasterAccountUser]
If this is too vague, let me know and I can expand.
I was able to get this to work.
Basically, you just do the standard aspnetdb.mdf with all the in-place security features.
Then you simply add a table with the same fields, and then you reference the
MembershipUser.GetUser(Page.User.Identity.Name);
So you own table will have a "masteruser" with this User.ProviderKey. Every "sub-user" then has the SAME masteruser guid on their record so that they all fall under the same account.
If anyone want more details on how i got this to work, i can happily provide them.
in my Project i need to define 3 roles :
SuperAdmin
Admin
RegisteredMembers
I also have Table which named "Users" that stores information such as:
fristName
lastName
Birthday
Username
Password
.
.
.
and etc
How can i make Roles recognize which user is for which Role when users try to log on to website?
First of all you creating a Users table is just the first step. You also need a Role table and a UserRole many-to-many relationship table to store which user belongs to which role(In a simple scenario).
That's for the database part of the whole concept.
Then, on the code side...since you're providing different tables than the ones in the AspNetMembership you need to also implement a custom membership provider, custom role provider and presumably a custom membership user.
Question No 1
I am familiar with role management, a particular member in a particular role can do this and access this functionally. What I need to do is Manage individual user, not the role he is in.
For example, lets say I create a role, called "Sales". I setup the role permission what the sales persons can do. Now i want to keep a check on individual user. For example if this is "john", i want to show him the records only he created. If his is peter, I want to show him only that records which he created, not by john or other sales people.
Is there a thing called "User Management" in ASP.NET that we can use? If not we have to create it ourselves and I believe the integration with ASP.NET "Role Management" will not be that smooth.
Question No 2.
I am using control for user login. I want to create a session at this time so I can keep track of which user is signed in so I can show him the records only pertaining to him. How can I do that?
Your Q1 isn't really about Role vs User management (ie: authorizations) at this point. It's about audit tracking within your application.
And the way you do that is you capture the ID of the user who created the record in question with the record, so that later you can filter on that ID.
Pseudo database structure
Table Sales
Field...
Field...
Field...
CreatedByUser int not null, -- Populate this on creation and never change it again
ModifiedByUser int not null - populate this on every row update including insert
See ASP.NET Profile Properties.
Assuming the records in the database correspond to a unique ID for a user, you can store the unique id in a profile property per user.
1) If you want to filter records by the creating user, you need to record in your table the ID of the user who created the record. You can access the name of current user through User.Identity.Name and their ID (provider-dependent) through User.ProviderUserKey.
2) Sessions are created automatically in ASP.NET and provided you have a properly configured MembershipProvider, you can retrieve all the needed user info using the User object as shown above.
It sounds like you are a little unfamiliar with ASP.NET Membership and Roles capabilities, because they are actually set up quite well to accomplish what you are describing. I would recommend checking out this tutorial series:
https://web.archive.org/web/20211020202857/http://www.4guysfromrolla.com/articles/120705-1.aspx
You are talking about Authentication and Authorization. For question 1 you and implement a custom authorization provider to allow for user level control http://msdn.microsoft.com/en-us/library/aa479048.aspx For question 2, once you log in and are Authenticated, the session contains a userprinciple object that has the info in it automatically.
We are building a multi-tenant website in ASP.NET, and we must let each customer configure their own security model. They must be able to define their own roles, and put users in those roles. What is the best way to do this?
There are tons of simple examples of page_load events that have code like:
if (!user.InGroup("Admin")
Response.Redirect("/NoAccess.aspx");
But that hard codes the groups and permissions in the code. How can I make it user configurable?
Perhaps put the configurable roles in a DB table, where you store the roles and tenant, and then the PagePermissions in another table, for example:
Table "Role"
RoleId, TenantId, Role
Table "PagePermissions"
PageId, RoleId
Table "UserRoles"
UserId, RoleId
Then in the page load check whether the User is in a RoleId that has permissions for that page, for example:
Select PageId FROM
UserRoles UR INNER JOIN PagePermissions PP
ON UR.RoleId = PP.RoleID
WHERE UR.Userid = #UserId AND PP.PageID = #PageId
If there are no rows returned then deny the user.
I would create a configuration system for the website that is easily managed in config-files. Where you could get typed members and use like this.
foreach(var group in ThisPageConfiguration.AcceptedRoleNames)
if (user.IsInRole(group))
...
Each customer could then configure their site in their configuration files... And every other type of things you'd want to configure.