asp.net Membership : Extending Role membership? - asp.net

I am been taking a look at asp.net membership and it seems to provide everything that i need but i need some kind of custom Role functionality.
Currently i can add user to a role, great.
But i also need to be able to add Permissions to Roles..
i.e.
Role: Editor
Permissions: Can View Editor Menu, Can Write to Editors Table, Can Delete Entries in Editors Table.
Currently it doesn't support this, The idea behind this is to create a admin option in my program to create a role and then assign permissions to a role to say "allow the user to view a certain part of the application", "allow the user to open a menu item"
Any ideas how i would implement soemthing like this?
I presume a custom ROLE provider but i was wondering if some kind of framework extension existed already without rolling my own?
Or anybody knows a good tutorial of how to tackle this issue?
I am quite happy with what asp.net SQL provider has created in terms of tables etc... but i think i need to extend this by adding another table called RolesPermissions
and then I presume :-) adding some kind of enumeration into the table for each valid permission??
THanks in advance

You can programmatically permit or not permit to the user to see some pages, or do some actions using for example the function IsInRole, and check if you let or not a user to do some actions.
HttpContext.Current.User.IsInRole("rolename")
You can make a class/or table with your permissions, and depend from the role that a user belong, to open, close, permit etc a lot of thinks on the same page. I have programming an idea like that on my programs, is very simple.
Here is an idea...
public enum csPermissions
{
pActionDelete = 1,
pActionEdit = 2 ,
...more actions...
}
private int[] AdminPermission = {
(int)csPermissions.pActionEdit,
(int)csPermissions.pActionDelete,
....
};
private int[] BackOfficePermission = {
(int)csPermissions.pActionEdit,
....
};
public static bool IsThisAllowed(csPermissions AskPermitForThisAction)
{
... questions here for all users roles...
... here is only an example .....
if (HttpContext.Current.User.IsInRole("Administator")))
{
for (int i = 0; i < AdminPermission.Length; i++)
if (AdminPermission[i] == (int)AskPermitForThisAction)
return true;
}
...
return false;
}
Hope this help.

You can use the framework to restrict access to entire pages or directories based upon roles. This can be configured in the web.config's authorization element. http://msdn.microsoft.com/en-us/library/wce3kxhd.aspx
Additionally, if you're using a SiteMap for your menu, and have configured authorization, you can use security trimming to restrict the menu. http://www.google.com/search?q=asp.net+security+trimming

Related

How can I restrict view access to a page type in SilverStripe to admin users only?

How can I restrict view access to a page type in SilverStripe to admin users only?
I'd prefer to do it through the code itself, but through the CMS would be good to know too.
I think this answer gets me most of the way there; I just need to find the Administrators group perhaps?
Yes, the answer you linked to is what you need to do. To get the ID of a group you could do something like this Group::get()->filter('Code', 'administrators')->first()->ID;.
Another alternative would be to check for permissions, e.g.
public function canView($member = null) {
return Permission::checkMember($member, "ADMIN") !== false;
}
As Willr mentions here checking for permissions would possibly be better.
You might find these APIs useful:
Permission
Group
Member

ASP.NET MVC Authorisation with CRUD roles

I need the ability to restrict what users can do in my application based on dynamic roles for CRUD.
For example the User/Index would need an authentication such as [ClaimsAuthorize("View", "User")] as oposed to [Authorise(Roles="Administrator")] so that I can check if the user has the security to view.
I have the user roles configured, but what the roles enable users to do is dynamic. An administrator can change the security levels with check boxes that will enable different security groups to do different things.
The main problem is doing this in Razor, I need something similar to #User.CanEditUsers, but I am not sure how I can go about doing this at all.
Any help would be greatly appreciated as I am having trouble finding the correct way to go about this.
Note that Authorizing users to see specific page elements differs from Authorizing for CRUD or other database operations, unless the elements point to operational Actions in Controller. Consider that you may have some elements that there's no need to be saw by a specific user, and don't have specific database operation. Till now we conclude that we need the following permissions :
Permission to See
Permission to Command
I believe that you can use Microsoft Role Provider for both parts. According to MSDN Documentation Considering that :
The Authorize attribute lets you indicate that authorization is
restricted to predefined roles or to individual users. This gives you
a high degree of control over who is authorized to view any page on
the site.
In The next step/question is how to do that?
I think 3 ways are available to meet our purpose:
Solution 1: Creating separate Views with specific page elements due to forwarding each user to related View. In this scenario we must
create separate controller actions too. we have to check user types
before each action like [Authorise(Roles="Administrator")]. We
forced to have static (Pre-defined) Roles and Accessibility. And in
one sentence Not a good solution because of redundancy and
instability.
Solution 2: Creating pages Dynamically simply by adding some if conditions for each access restricted element in One Page(for
example Edit Page). That is like employing #if
(User.IsInRole("Admin")) to authorize specific users and show
related page elements like buttons. In Controller side we can use
if conditions (not as FilterAttribute due to add dynamic
functionality based on generated/added new roles) and control valid
transactions against database. Although FilterAttributes add some great functionalists (like performance optimization). In one sentence A moderate solution.
Solution 3: Act like solution 2, just fix Controller problem by
creating our own custom FilterAttribute for authorization. That will
inherited from AuthorizeAttribute and overrides the OnAuthorize
method to do what you need only for Operations.
For Example :
public class TableAuthorizeAttribute : AuthorizeAttribute
{
public enum TableAction
{
Read,
Create,
Update,
Delete
}
public TableAction Action { get; set; }
public override void OnAuthorization(AuthorizationContext filterContext)
{
base.OnAuthorization(filterContext);
//do custom authorizization using Action and getting TableEntryID
//from filterContext.HttpContext.Request.QueryString or
//filterContext.HttpContext.Request.Form
}
}
And its usage will be like this :
[TableAuthorize(Action=TableAuthorizeAttribute.TableAction.Update)]
Here is complete example about above concept. Here is complete example for creating dynamic AuthorizeAttribute for authorizing new roles added to application.
Solution 3 in one sentence A perfect but Complex Solution.
Note that by using FilterAttribute before Actions we have limited our application to static/predefined roles. No need to use another Data Structure or generate tables in Database.
You need to separate the concept of roles from groups in your design.
A role gives fixed permissions to perform certain actions in your application. A group is a set of users. What your administrator is really doing is to assign groups of users to different roles.
Your authorization code should be able to rely on fixed roles, e.g. an "ViewUserInfo" role. Then implement the administration interface so that when the admin enables a user to view userinfo, you add that user to the "ViewUserInfo" role.
The same goes with groups: If an entire user group is granted the right to view user info you should add that group to the "ViewUserInfo" role. To introduce the concept of groups and be able to add groups to roles you can't rely on the standard SimpleRoleProvider, so you probably have to implement your own role provider as well as a group provider.
In the end some workaround might be easier, but this is, in my opinion a cleaner architecture.
From the horse's mouth: "Role management helps you manage authorization, which enables you to specify the resources that users in your application are allowed to access. Role management lets you treat groups of users as a unit by assigning users to roles such as manager, sales, member, and so on." (ref: http://msdn.microsoft.com/en-us/library/5k850zwb%28v=vs.100%29.aspx)
Users can be in multiple roles, and you can leverage action filters to get fine-grained control of access to the various resources in your site:
[Authorize(Roles="Contributor, Designer, Reviewer")]
I think the "dynamic" aspect you are after revolves around Administrators being able to add and remove users on-demand from the roles which provide access to those resources, which is pretty typical.
The idea of constantly changing the permissions your roles grant would be a bad design choice.

Accesing data from Roles into gridview

Is it possible to retrieve the user details into grid view, from Roles assigned through Administrator website?
Is there any other way to do so?
You can also achieve same kind of thing by making the extra column of roles in the database and extracting the value of role during the time of login.
Now you can store this role in any kind of variables like cookies ,sessions etc and performing the following check in the masterpage
if(session[role]==null)
{
Response.Redirect("Home.aspx");
}
else if(session[role]!="User")
{
Response.Redirect("Home.aspx");
}

Custom fields in ASP.Net Login/Register?

I have to edit the Login/Registration that ASP provides to include a custom dropdown ("BranchID") menu that saves to the database so each user has its own Branch. I am using ASP Membership system, and of course it saves to the ASPNETMDF database it creates. Googling has net me some results but I am quite confused. I know there are "User Profiles", and I I can save this Profile data, but what I am not quite sure is if its a temporary measure or if it does record to the database.
I could make my own custom membership system, use the built it and adapt it or use the user profiles. What is the best course of action? I'd vastly prefer to adapt/edit the built in Membership system and add the data I require to it but I still don't haven't a clear answer to what I should do or what's best.
You have two choices:
Create a CustomMembershipProvider , and if you need to a CustomRoleProvider, you can do this by implementing .NET's MembershipProvider. Sample: http://www.codeproject.com/Articles/165159/Custom-Membership-Providers
Create a separate table that stores additional user information, i.e., "BranchID", and add a one-to-one relationship between your table and .NET's Membership
It's really up to you which one you choose.
MembershipProvider is pretty easy to extend. Assuming the branch is something they have to select to authenticate? You should be able to extend authenticate to do something like:
public class MyCustomMembershipProvider : MembershipProvider
{
/*
....
*/
public bool ValidateUser(string username, string password, string branch)
{
return (::ValidateUser(username, password) && MyCustomRoutine(username, branch));
}
}

Switch to SQL membership provider from AD membership provider runtime

In my asp.net application admin functionality, I am trying to combine AD authentication and form authorization for creating the users, roles and Assign users to roles etc. I have configured MembershipADProvider and AspNetSqlMembershipProvider in my web.config with MembershipADProvider as the default one. After user logs in using AD authentication, I need to switch/assign my membership object to use AspNetSqlMembershipProvider in order to get all the users from membership object (from dbo.aspnet_Users table). How do I switch the provider during run time? I have tried different approaches after searching for this issue and none of that seem to work for me so far.
Here are couple of approaches I tried:
1. foreach (MembershipProvider mp in Membership.Providers)
{
if (mp.Name == "MembershipADProvider")
{
Membership.Providers.Remove(MembershipADProvider");
MembershipUserCollection users = Membership.GetAllUsers();
ddlUsers.DataSource = users;
ddlUsers.DataBind();
break;
}
}
Membership.Providers.Remove(MembershipADProvider"); - doesn't work as it's not supported..
Also, tried to clear the Membership.Providers and then add only the type of AspNetSqlMembershipProvider which are also not supported.
I can't set Membership.Provider with value from
Membership.Providers["AspNetSqlMembershipProvider"] as Membership.Provider is a read only property.
I tried to swtich the connection string between 2 providers, which didn't swtich the provider, as both are different types of providers..if both were sqlserver providers this would have worked I believe.
Please let me know if anybody has successfully implemented or if at all this is a plausible approach. Thank You!
You would pass an explicit provider to your code, rather than taking a dependency on Memebership directly (which just wraps the one flagged as default in the config). There is no need to swap them in and out at runtime, think how this would affect thread safety.
So rather than saying Membership.GetAllUsers(); you would do something like (I don't have a compiler to hand):
public UserSerivce : IUserService
{
private MembershipProvider provider;
public UserService(MembershipProvider provider)
{
this.provider = provider;
}
public IEnumerable<MembershipUser> GetUsers()
{
return provider.GetAllUsers();
}
public void DoSomethingElseUseful()
{
...
}
}
And then to use it for a particular provider:
var service = new UserService(Membership.Providers["mySqlMembershipProvider"]);
var users = service.GetUsers();
Or if using AD specific code:
var service = new UserService(Membership.Providers["myADMembershipProvider"]);
var users = service.GetUsers();
Using DI in this way also helps keep code testable.
If all you need a list of users in the aspnet_Users table, just connect to your database with System.Data.SqlClient objects and query the table. There is no reason (that you mentioned) you need to use a membership provider to get that data.
Having said that, your membership/authentication scheme sounds like it may have some design issues, perhaps best tackled in a different question, but I think it might be useful to you if you sought comment on what you are trying to accomplish overall with the multiple membership providers.
Edit: I found some potentially useful posts on using multiple membership providers. It looks like the general idea is to implement custom code handling the Login.Authenticate event on your Login control, and use Membership.Providers["ProviderName"].ValidateUser to attempt authentication with each provider.
http://www.stevideter.com/2008/03/20/using-two-membership-providers-for-aspnet-logins/
http://forums.asp.net/p/1112089/1714276.aspx

Resources