User configurable security in multi-tenant ASP.NET website - asp.net

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.

Related

How to get Roles from using SimpleMembership?

I am developing a MVC4 application with SimpleMembership. I have a table - "userInfo" in which I am storing user's information such as Name, Email, Address, Phone, Role etc. When I register a user, data is stored in this table and webpages_Membership. No data is stored in other Membership tables (OAuthMembership, Roles, UserInRoles).
When I login a user, it is validated using :
if (ModelState.IsValid && WebSecurity.Login(Model.Name, Model.Password, false))
it returns "True" but after this, I need to get the role of the registered user.
In SimpleMembership, does "Roles and UserInRoles" table provide registered user role or can I query the "userInfor" table and get roles from this table.
Please advice
Thanks in Advance
to get all available roles, assuming you have enabled Roles and added at least one..
var roles = (SimpleRoleProvider)Roles.Provider;
var allRoles = roles.GetAllRoles();
to get specific user's roles.
var userRoles = roles.GetRolesForUser("specificusername");
ref MSDN
Simple Membership does not come with any out of the box management pages for Roles. You are on your own to create them, or manage them directly through code/sql/ef etc..
Code examples...
Check for and creation of Admin role:
if (!Roles.RoleExists("Admin"))
Roles.CreateRole("Admin");
Adding user to role on creation:
if (!Roles.GetRolesForUser("specificusername").Contains("Admin"))
Roles.AddUsersToRoles(new[] {"specificusername"}, new[] {"Admin"});
ref adding-security-and-membership
You can user Roles.GetRolesForUser Method after your user logged in
Gets a list of the roles that the currently logged-on user is in.
Or if you want to check whether current user is in specified role you can use Roles.IsUserInRole Method

Multiple ASP.NET Membership roles in the same Website

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.

how to make Roles and manage Users?

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.

How to use ASP.NET Membership for User Defined Permissions

I have a simple ASP.NET MVC 3 application. I have the database I designed for the application, which corresponds to a domain model (in an App.Domain assembly).
I auto-generated the Application Services Membership tables and added them to the application database. Membership creation is working fine.
I created a 'Permission' table which has a composite PK made up of UserId (from the auto-generated aspnet_Users table) and ContentId (from the Content table holding the application content).
The idea is to allow users to allocate permissions to other users for the content they create.
My plan is to then place logic in the Controllers that goes something like:
Collapse | Copy Code
Guid currentUser = (Guid)Membership.GetUser().ProviderUserKey;
int[] accessible = (from p in context.Permissions
where p.UserId == currentUser
select p.ContentId).toArray();
Then to get the content for the current user, something like this:
Collapse | Copy Code
IEnumerable<content> content = context.Content
.Where(x => x.PublicAccess < 3
|| accessible.Contains(x.ContentId));</content>
If I have made any sense, can anyone tell me if this is a normal way to handle user defined permissions.
Also, this code doesn't work because it won't cast the linq to an int[]. Any help with that?
Typically permissions are handled by the role subystem. You do something like this:
if (User.IsInRole("RoleName")) {
DoWhateverTheUserIsAllowedToDo();
}
You can combine this with dynamically assigned content permissions by looking up what roles or users are assigned to the content, and checking if the user is in that role, or if the users is specifically allowed.
Role based permission scales better than assigning users to specific pages. As the number of pages grow, assigning users to pages becomes a nightmare. So you typically assign roles to pages, then assign users to roles.
Your code seems to want to do a lot of work, returning lots of different content items. Typically, you know what item you want to control access to. So you might do something like:
var roles = Roles.GetRolesForUser()
var content = from p in context.Permissions where p.ContentID == contentID
&& roles.Any(x => p.Roles.Contains(x)) select p;
But, there are so many ways to do this, you will have decide what works best for you.
I don't understand your last bit about not casting to an int[]. I assume .toArray() is a typo, it should be .ToArray(). And if ContentID is an int, .ToArray should create an int[].

get current logged in userID in aspnet mvc membership

i am trying to show a list of users of my application "school", when admin logs in then he can view all the users in list but when school principals logins, he should get only users of his school, So i thought to get the current loggedIn userId first and then by that userId i'll get schoolId since userId is foreign key in school table...once i'll get the schoolId i can show the members of that school.
But my problem is how to get the UserID of currently loggedIn. I'm using MVC 1.0 Asp.Net -- "Membership"
if my logic above is wrong then please tell me the alternate good idea, so that principal can see only his users list..
Based on this question and answer by J. Pablo Fernández you can get the user id of the current user with the following code:
//It will only be a Guid if you are using SQL Server as the DB as oppose to MySQL
Guid userGuid = (Guid)Membership.GetUser().ProviderUserKey;
Here is the MSDN Documentation.
The Simple Solution
With the scenario you describe you would only be able to do this by retrieving the User information with the data stored in the HttpContext.Current.Identity. For example, if the HttpContext.Current.Identity.Name is the Username, then you would use that value to retrieve the User data for the principal that should include the UserId you can use to locate the appropriate school.
Alternate Solution
You might consider storing the SchoolId in the user's profile so that it is more easily accessible.
The easiest way that I've tried
You have to include Microsoft.AspNet.Identity
using Microsoft.AspNet.Identity;
Then use it like this
var userId = User.Identity.GetUserId().ToString();

Resources