MVC And Control Based Authorization - asp.net-mvc-4

Is it possible to define authorization at control level ? If so what is the best practice ?
Consider I have input control named daily wages (text box). userRoleOne is an user role who supposed to see this field, other user roles should not see this field . what is the best practice to do this ?

Yes, it's possible. Current instance of HttpContext is accessible in Razor's views by name Context, so you can check is user in role, or not:
#if (Context.User.IsInRole("userRoleOne"))
{
Html.TextBox("dailyWages", "")
}
It should work without any additional code with ActiveDirectoryMembershipProvider and Windows Authentication, but may not work with Forms Authentication and other memberships.
In last case you should manually create an object of GenericPrincipal class in Application_AuthenticateRequest method of Global.asax (see details).

Related

MVC 4 model field custom authorization

We are creating an MVC 4 application that requires the user to be authorized to view and/or interact with certain model fields based on his/hers role membership.
For example if the model has a field SSN, the user should be allowed to view this field only if he/she is a member of the admin role. Once displayed the user should be able to modify it only if member of the profile_admin role. In other words, the SSN field should not be rendered if the user is not a member of the admin role and should be disabled if the user is not a member of the profile_admin role. Which roles have the permissions should be controlled by the site admin via the admin UI.
One possible solution is to wrap the SSN field in a partial view and then handle the rendering in our custom view engine. However, this method will require every field that we want to control to be in a partial view and it would require code change if the user wants to control another field (say HireDate)
We were hoping that we could achieve this by using a custom attributes in the metadata class like so:
[CustomFieldAuthorizeAttribute]
public string SSN { get; set; }
We would keep the authorization information for each field in the database like so:
FieldName RoleId AllowView AllowEdit
SSN 1 True False
When the attribute executes it will check the role membership of the currently logged user and will determine the permissions to view and edit for this field and then it will inject the appropriate html attributes like class="hidden" or disabled="disabled".
This way if the user wants to add authorization for another field, all we need to do is create a record in the database for this field. The custom attribute will pick it up from there.
Is it possible to achieve such functionality
Thank you.
For those of you that are facing this situation, I used the concept described in this article to create the necessary functionality. With a little tweaking, the solution worked exactly as required.
Thanks.

SimpleMembershipProvider roles not accessible

I have MVC4 application which uses SimpleMEmbershipProvider for authentication mechanism.
Everything works fine, apart of when I return to the application and authenticate using persistant cookie.
I am authenticated fine, but cannot access roles that I am assigned to. Effectively, cannot access roles at all:
string.Join(",", Roles.GetRolesForUser(User.Identity.Name))
returns empty string
What might be causing that?
This can happen when the SimpleMembershipProvider hasn't been initialized. The example MVC forms authentication template assumes that you'll be allowing anonymous access to your site and doesn’t initialize the membership provider until you go to the login page. However, a more common security technique is to require a login for any site access and to define menu choices in the _layout page to be determined by roles. But, if you use the persistent cookie, you don’t revisit the login page so the roles for the authenticated user aren’t loaded from the membership database.
What you want to do is initialize the provider when the user enters the site so that values get loaded. To do this, you want to add the following filter in the RegisterGlobalFilters method of the FilterConfig class in the App_Start folder
filters.Add(new YourAppNameSpace.Filters.InitializeSimpleMembershipAttribute());
This will cause the user data to be loaded from the database when a cookie authenticated user enters the site.
Another alternative technique is to add the [InitializeSimpleMembership] decorator to any controller method that cookie autheticated users might enter directly. This is kind of messy though if you have to put it on a lot of controllers. Therefore, putting it in the global filter is better in most cases.

Yii RBAC, Role change in runtime

I am building up a dynamic RBAC system for Yii and I don't know how to handle this problem:
The moderators can change the roles of the Users, furthermore the User can change it too by getting a different qualification (let's say achievement, so s/he can do more stuff and it can happen both ways).
What happens, when the role is changed Backwards (a role with less right) or Forwards (a role with more right) when s/he is logged in? Cannot access the functions he just got the right to use? Or can still access the functions until a logout/relog action?
Thanks your help in advance.
The effect of changing the authorization assignment will be inmediate.
Only the successive calls to IWebUser::checkAccess() issued in the same request may return cached values, since the default implementation of IWebUser, i.e. CWebUser, uses a static attribute to cache the calculated permissions.
To clarify the procedure, you will be calling IAuthManager::revoke() on the old permissions and IAuthManager::assign() on the new ones.
Edit
Sometimes you store session information through the IWebUser::setState() method; if the state of the currently logged user shall change along with the permissions, e.g. you store the current user's role name, you must take this into account and either call IWebUser::clearState() or IWebUser::logout() followed by IWebUser::login() –the latter also clears the cached permissions in the CWebUser implementation.
CWebUser::_access is declared private, so you will have to declare a new attribute if you want to override the default implementation.

MVC 4 : Passing around user group data

I am in the process of rewriting my PHP website in ASP.NET and writing the membership system.
I understand I can extend MembershipUser to add member specific properties but how can I pass around boolean group information such as Use Search, Edit Posts etc which are not user specific? Is there a framework item I am missing or should I just create a super object to pass this and other settings around?
Essentially what I want it an efficient way to access the users group properties in my controllers.
Apart from extending the MembershipProvider, you can also extend RoleProvider. RoleProvider is in charge of checking to which group a user belongs to, registering new roles, adding user to role(s), etc. To work with roles you will use Roles class which contains a lot of static methods.
In addition to this, each time you hit a Controller, you can query HttpContext.User property which implements IPrincipal. This property has method IsInRole that is used to communicate with RoleProvider to obtain information if a user is in specific group or not.
Also, in order to allow access to controllers or actions you can use Authorization attribute and list specific roles that have access to the controller.
The roles can be stored in a cookie (to cache them) or you can implement Application_AuthenticateRequest in global.asax and initialize GenericPrincipal manually. This object is passed over to HttpContext.User. The constructor of this object accepts an array of roles that are queried with IsInRole method.
protected void Application_AuthenticateRequest(Object sender, EventArgs e)
{
// Check if user is authenticated
if (HttpContext.User != null)
{
// Extract roles from a cookie if you used FormsAuthentication
// or read them from a cookie or from some other cached location
// Split roles into array of strings
var roles = listOfRoles.ToArray(); // If it is stored in a List<string>.
var identity = HttpContext.User.Identity;
var principal = new GenericPrincipal(identity, roles);
HttpContext.User = principal;
}
}
The above code is not tested. I wrote it from top of my mind. It should give you a pretty good picture how to cache roles and to use them in the most efficient way.
UPDATE: In case that you need more advanced options where each role can have one or more functionality like your "Use search", "Can do something", "Can do that", I would implement the following security logic:
Users
Roles (users belong to roles)
AccessRight (Role can have one or more access right).
UsersRoles table would be for adding users to specific roles.
RolesAccessRights table is where you define specific rights to each role.
User never talks to Functionality. (BTW, this naming convention is just an example, you will follow your naming conventions).
At my last work this is how we implemented the Audit system (it was Web Forms based). However, in MVC you could override AuthorizationAttribute to check user's role and to check if Role has defined access rights. Considering that you have specific security requirement, you would have to use this attribute on every action where you see the need and necessity.
If you plan to implement this logic, forget about Membership, MembershipUser and Roles. Honestly, I don't use these classes any more. I have my own custom security that I implement and which I used in the last 4 projects without any need for update or modification.
UPDATE 2: The security solution that we used was based on custom MembershipProvider and RoleProvider. Thinking about it now, it was a mistake to rely on that because access to AccessLevel table had to be mapped via Entity Framework. Therefore we had to ways to query our security tables.
My suggestion to you would be to ignore Membership- and Role-related classes completely. The first reason is that you would avoid bothering yourself with unnecessary methods and properties when you override the providers. There would be too many methods with throw new NotSupportedException() in the method body.
Suggested implementation
You will need the following tables:
Users - (You need at least three columns UserId, UserName, Password). If you want to hash the password, you might have to store salt as well. Other columns like FirstName, LastName, etc. I would suggest you to store in a different table and link it with UserId. As for UserId type it's up to you whether you would use int or Guid.
Roles - (You need at least two columns RoleId, RoleName). Again, as with UserId, it is up to you which data type you want to use.
UsersRoles - Store UserId and RoleId. You might want to store properties such as whether the role IsActive which is a bit value.
AccessRights - This is where you would store a key of your access right. In your case that is like UseSearch, EditPosts, DeletePosts, etc. Here you should use at least three columns AccessRightId, AccessRightKey and AccessRightDescription. This description field will turn to be pretty valuable if you have a lot of access right keys.
RolesAccessRights - This is where you define to which role you have added specific access rights. Also have IsActive bit value in order to disable the specific access right to a role.
In MVC you would override AuthorizationAttribute. In this attribute you would specify a list of access rights that have access to controller and/or actions. How you plan to do this is entirely up to you, but I would create an enum with a list of values that are the same as AccessRightsKeys. That way you can use strongly typed access rights instead of string based list. For more information about implementing custom authorization attribute have a look at the references list.
Inside of this attribute, you would read User ID and retrieve the roles. Compare the AccessRightsKeys that you specified against the roles (RolesAccessRights table) to see if the role has access right and whether the rule is active.
As for the solution based implementation I would implement Security service layer which communicates with Security-based repository and unit of work solutions. Because you are using MySQL I don't know which ORM you can use or would you have to rely on ADO.NET with OLEDB providers for MySQL.
My usual approach is a top-down approach. I implement from the high up (like Presentation layer) and go down towards data access layer. That way at the end I have only those methods which I really use and there is no redundancy.
Well, I hope this gives you some picture on how to this. As for time it takes, you can do this in about 8-10 hours.
Reference:
Implementing a Role Provider
Roles Class
How to: Create a Custom AuthorizationAttribute

Custom PrinciplePermission Authentication

Our system uses a custom roles, and authentication system to Authenticate users.
I am now looking into the service side validation/security.
I want implement our custom Authentication, Authorization on the wcf too.
I have done some investigation, it looks like I could use the PrinciplePermission attribute on the contracts to allow/deny access. The default just calls the IsInRole method on the IPrinciple and the IsAuthenticated on the IIdentity.
So I have 2 questions:
How do implement my own custom principle which has additional data/methods?
How do I add addition checks to the PrinciplePermissions? e.g (IsExternal which will check if they are accessing the service from the intranet or internet [have a mechanism to monitor this already])
Thanks
After some experimenting I came up with a custom written solution:
I based my solution in Kyle McClellan's Authorisation Sample. I adapted the attributes to look at a custom class to retrieve the user.
To get around the async problem I loaded the user and his relevant data in the App.xaml prior to instantiating the MainPage, I then make use of a global singleton, which I called SecurityContext, to access user data.
The SecurityContext is an in-memory store of the user data that can be accessed clientside.