Best practices for control permissions? - asp.net

Hey all, I need some advice on this...
We have certain permissions setup in the database for certain levels of control a user can have over the application. Disabled, ReadOnly and Edit.
My question is: Are there more generic/better ways to handle permissions applied to a form element on the page than writing a security method/check per page to enable/disable/hide/show proper controls depending on the permissions allowed?
Anyone have any experience handling this in different ways?
Edit:
I just thought about the possibility of adding constants for each layer that needs security and then adding an IsAuthorized function in the user class that would accept a constant from the form that the control is on, and return boolean to enable/disable controls, this would really reduce the amount of places I'd have to hit when/if I ever need to modify the security for all forms.
Cheers!

Sorry for going slightly off-topic here, but learn from my mistake:
I had a simple web app one time that I was developing and I thought that I'd setup 3 levels of security: limited read-only (public), read-limited write (user), read-write (admin). The users table had a level of security in it and everything worked fine... until I needed finer control over security levels as the project grew. It all started with a user that needed more than user control in one area of the program but not full admin control.
What I should have done was setup an expandable system with finer control even though I didn't need it at first. This would have saved me sooo much time.

I think there are more possibilities than you are considering.
Hidden/Visible - is the field visible or not
Blanked/System/Unchanged - does the system initially set the value to blank, or to some business-rule-provided value, or is it left as-is
ReadOnly/Editable - can the user change the value
Required/LeaveBlank/Optional - is the field required to not be blank, or can it be left blank assuming it was blank to begin with, or is it optional and can be blank in any case
Also you need to consider a lot of factors that go into making the decision
Role - usually the user has 1 or more roles, and those roles can allow or disallow different possibilities
Status - the status of the object in question often controls which fields are editable, regardless of role
Object - often the values of the object itself determine what is allowed when, beyond just's it's status
Task - you might break down editing things into more than just read and edit
Section - I often want to control the settings for an entire section of the object or screen, and all the controls inherit those settings, but can override them on an individual basis if needed
Implementation?
First, make sure you have a clear vision of how the page lifecycle is handled. Mine usually goes something like this.
Get the object they are editing, usually from session state, sometimes if they are doing a "new" operation you may need to create a stub data structure for them to work on
If this is the first time the page is loading up, populate choices into dropdowns, this is usually a generic process, done only once
If this is a postback, update the object being edited by reading in values off the controls
Process events such as button clicks
Run through all your business edits, these should alter the data structure they are editing
Update the visibility and editability of the controls based on all the data you have on hand
Populate the controls with the data from the object being edited, including validation messages, or error messages

You may want to check how django handles forms and validates them. Forms are handled like models, they have their own class, so their field list, validation rules and display logic is no more scattered throughout the view, the controller and the helper. With such a structure, it's pretty clear where the hidden/readonly/editable logic belong.
It seems that such a feature is not yet implemented in rails. It's not only a time-saver, it keeps your code clean and structured. You could start by creating a base class for forms, where validation is separated from the controller.

To work properly, I have found that access levels should be in this increasing order:
NONE, VIEW, REQUIRED, EDIT.
Note that REQUIRED is NOT the top level as you may think it would be since EDIT (both populate & de-populate permission) is a greater privilege than REQUIRED (populate-only permission).
The enum would look like this:
/** NO permissions.
* Presentation: "hidden"
* Database: "no access"
*/
NONE(0),
/** VIEW permissions.
* Presentation: "read-only"
* Database: "read access"
*/
VIEW(1),
/** VIEW and POPULATE permissions.
* Presentation: "required/highlighted"
* Database: "non-null"
*/
REQUIRED(2),
/** VIEW, POPULATE, and DEPOPULATE permissions.
* Presentation: "editable"
* Database: "nullable"
*/
EDIT(3);
From the bottom layer (database constraints), create a map of fields-to-access. This map then gets updated (further restrained) at the next layer up (business rules + user permissions). Finally, the top layer (presentation rules) can then further restrain the map again if desired.
Important: The map must be wrapped so that it only allows access to be decreased with any subsequent update. Updates which attempt to increase access should just be ignored without triggering any error. This is because it should act like a voting system on what the access should look like. In essence, the subsequent layering of access levels as mentioned above can happen in any order since it will result in an access-level low-water-mark for each field once all layers have voted.
Ramifications:
1) The presentation layer CAN hide a field (set access to NONE) for a database-specified read-only (VIEW) field.
2) The presentation layer CANNOT display a field when the business rules say that the user does not have at least VIEW access.
3) The presentation layer CANNOT move a field's access up to "editable" (nullable) if the database says it's only "required" (non-nullable).
Note: The presentation layer should be made (custom display tags) to render the fields by reading the access map without the need for any "if" statements.
The same access map that is used for setting up the display can also be using during the submit validations. A generic validator can be written to read any form and its access map to ensure that all the rules have been followed.
(Also see thread: Best Practices for controlling access to form fields)

Related

Dynamic Access Control for entities in symfony 4

I try to manage the access rights for users to edit or view different articles.
Articles can be created dynamically and the rights should be editable for every article.
In my case, I have a User object and multiple other objects (Article, and more...).
I need to check if a User can read or write any kind of object.
I actually see there is a method Voters, but they only can manage User groups?
Can somebody help me?
A Voter can decide almost anything - usually it's based on a user's permission, but it doesn't have to be - I've used one as a 'feature flag' check, with a value fetched from a configuration, or database entry to show something - or not, as an example.
The page on voters has an example on viewing, or editing a database record (a Post entity, via a $this->denyAccessUnlessGranted('edit', $post);.
In your instance, the voter would be passed the 'attribute', the object (Article, etc) you want to check on, and gets the current user from a service. If that user has the appropriate permission to read/edit/delete the Article or other object, it returns true.

Control Level Security in ASP.Net for server side and client side controls

I have a software application in ASP.Net, I have different buttons and link labels, each button has classes, for example the add buttons have btnAdd as their classes, and some of the labels are using similar classes.
What would be the best approach if i want control level security, for example a user with ID =2 should not be allowed to click on AddNew button of some ABC page.
My Solution:
I have several solutions in mind, for example to store the names of the classes in a table and link that table with Pages Table and bring data into Hidden text field and then on page load we will check either this control is allowed or not. Like btnAdd is allowed to be visible and btnSearch is not.
Please find the image attached for further clarification.
Let's say we have permissions in hidden field in some format. But will it be the right approach of doing this way? please suggest some better solution.
Use Razor to generate the buttons
You could structure your Razor view to incorporate a view model containing the user's permissions. Then you could add each button to the page based on whether or not the user has permission to perform that action.
Let's say you have your model (we will call it Users) contain a permission set that you can access via Users.UserPermissions. Your UserPermissions property might have a CanAdd and a CanSearch boolean. You'd populate this model with the data from your database regarding the user in question, and then render the page like this:
<div class="container">
#{
if (Model.UserPermissions.CanAdd)
{
<button class="add">Add</button>
}
if (Model.UserPermissions.CanSearch)
{
<button class="search">Search</button>
}
}
</div>
Then check your permissions server-side
This means the button will only get added to the interface if the user has permission to perform that action.
[HttpPost]
public ActionResult Index(UserViewModel model)
{
var user = User.GetByEmail(userEmail);
if (user.CanAdd)
{
myClass.Add(model.ThingsToAdd);
}
if (user.CanSearch)
{
myClass.Search(model.ThingsToSearchFor);
}
return View()
}
When the users submits the form, the program is also checking the user's permissions on the server to ensure teh validity of the request. Even if an attacker managed to find a sneaky way to perform a function they aren't allowed to perform, the program can still limit the attacker from performing said action by checking the data being returned, and verifying that the user is actually allowed that functionality.
It's the equivalent of trying to withdraw money from a bank - the teller should check to make sure you have some money in the bank first before they hand you any cash.
What you should NOT do
Absolutely never rely on hidden fields or objects returned from the client to determine a managed variable result. You should always assume that data sent from the client is unsafe or tampered. Run your checks, sanitise your inputs, and try to verify everything the client sends you is true.
Things like permissions to perform actions should always be checked server-side and never anything else.

Flex-Cairngorm/Hibernate - Is EAGER fetching strategy pointless?

I will try to be as concise as possible. I'm using Flex/Hibernate technologies for my app. I also use Cairngorm micro-architecture for Flex. Because i'm beginner, i have probably misunderstand something about Caringorm's ModelLocator purpose. I have following problem...
Suppose that we have next data model:
USER ----------------> TOPIC -------------> COMMENT
1 M 1 M
User can start many topics, topics can have many comments etc. It is pretty simple model, just for example. In hibernate, i use EAGER fetching strategy for unidirectional USER->TOPIC and TOPIC->COMMENT relations(here is no question about best practices etc, this is just example of problem).
My ModelLocator looks like this:
...
public class ModelLocator ....
{
//private instance, private constructor, getInstance() etc...
...
//app state
public var users:ArrayCollection;
public var selectedUser:UserVO;
public var selectedTopic:TopicVO;
}
Because i use eager fetching, i can 'walk' through all object graph on my Flex client without hitting the database. This is ok as long as i don't need to insert, update, or delete some of the domain instances. But when that comes, problems with synchronization arise.
For example, if i want to show details about some user from some UserListView, when user(actor) select that user in list, i will take selected index in UserList, get element from users ArrayCollection in ModelLocator at selected index and show details about selected user.
When i want to insert new User, ok, I will save that user in database and in IResponder result method i will add that user in ModelLocator.users ArrayCollection.
But, when i want to add new topic for some user, if i still want to use convenience of EAGER fetching, i need to reload user list again... And to add topic to selected user... And if user is in some other location(indirectly), i need to insert topic there also.
Update is even worst. In that case i need to write even some logic...
My question: is this good way of using ModelLocator in Cairngorm? It seems to me that, because of mentioned, EAGER fetching is somehow pointless. In case of using EAGER fetching, synchronization on Flex client can become big problem. Should I always hit database in order to manipulate with my domain model?
EDIT:
It seems that i didn't make myself clear enough. Excuse me for that.
Ok, i use Spring in technology stack also and DTO(DVO) pattern with flex/spring (de)serializer, but i just wanted to stay out of that because i'm trying to point out how do you stay synchronized with database state in your flex app. I don't even mention multi-user scenario and poling/pushing topic which is, maybe, my solution because i use standard request-response mechanism. I didn't provide some concrete code, because this seems conceptual problem for me, and i use standard Cairngorm terms in order to explain pseudo-names which i use for class names, var names etc.
I'll try to 'simplify' again: you have flex client for administration of above mentioned domain(CRUD for each of domain classes), you have ListOfUsersView(shows list of users with basic infos about them), UserDetailsView(shows user details and list of user topics with delete option for each of topic), InsertNewUserTopicView(form to insert new topic) etc.
Each of view which displays some infos is synchronized with ModelLocator state variables, for example:
ListOfUsersView ------binded to------> users:ArrayCollection in ModelLocator
UserDetailsView ------binded to------> selectedUser:UserVO in ModelLocator
etc.
View state transition look like this:
ListOfUsersView----detailsClick---->UserDetailsView---insertTopic--->InsertTopicView
So when i click on "Details" button in ListOfUsersView, in my logic, i get index of selected row in ListOfUsers, after that i take UserVO object from users:ArrayCollection in ModelLocator at mentioned index, after that i set that UserVO object as selectedUser:UserVO in ModelLocator and after that i change view state to UserDetailsView(it shows user details and selectedUser.topics) which is synchronized with selectedUser:UserVO in ModelLocator.
Now, i click "Insert new topic" button on UserDetailsView which results in InsertTopicView form. I enter some data, click "Save topic"(after successful save, UserDetailsView is shown again) and problem arise.
Because of my EAGER-ly fetched objects, i didn't hit the database in mentioned transitions and because of that there are two places for which i need to be concerned when insert new topic for selected user: one is instance of selectedUser object in users:ArrayCollection (because my logic select users from that collection and shows them in UserDetailsView), and second is selectedUser:UserVO(in order to sync UserDetailsView which comes after successfull save operation).
So, again my question arises... Should i hit database in every transition, should i reload users:ArrayCollection and selectedUser:UserVO after save in order to synchronize database state with flex client, should i take saved topic and on client side, without hitting the database, programmatically pass all places which i need to update or...?
It seems to me that EAGER-ly fetched object with their associations is not good idea. Am i wrong?
Or, to 'simplify' :) again, what should you do in the mentioned scenario? So, you need to handle click on "Save topic" button, and now what...?
Again, i really try to explain this as plastic as possible because i'm confused with this. So, please forgive me for my long post.
From my point of view the point isn't in fetching mode itself but in client/server interaction. From my previous experience with it I've finally found some disadvantages of using pure domain objects (especially with eager fetching) for client/server interaction:
You have to pass all the child collections maybe without necessity to use them on a client side. In your case it is very likely you'll display topics and comments not for all users you get from server. The most like situation you need to display user list then display topics for one of the selected users and then comments for one of the selected topics. But in current implementation you receive all the topics and comments even if they are not needed to display. It is very possible you'll receive all your DB in a single query.
Another problem is it can be very insecure to get all the user data (or some other data) with all fields (emails, addresses, passwords, credit card numbers etc).
I think there can be other reasons not to use pure domain objects especially with eager fetching.
I suggest you to introduce some Mapper (or Assembler) layer to convert your domain objects to Data Transfer Objects aka DTO. So every query to your service layer will receive data from your DAO or Active Record and then convert it to corresponding DTO using corresponding Mapper. So you can get user list without private data and query some additional user details with a separate query.
On a client side you can use these DTOs directly or convert them into client domain objects. You can do it in your Cairngorm responders.
This way you can avoid a lot of your client side problems which you described.
For a Mapper layer you can use Dozer library or create your own lightweight mappers.
Hope this helps!
EDIT
What about your details I'd prefer to get user list with necessary displayable fields like first name and last name (to display in list). Say a list of SimpleUserRepresentationDTO.
Then if user requests user details for editing you request UserDetailsDTO for that user and fill tour selectedUser fields in model with it. The same is for topics.
The only problem is displaying list of users after user details editing. You can:
Request the whole list again. The advantage is you can display changes performed by other users. But if the list is too long it can be very ineffective to query all the users each time even if they are SimpleUserRepresentationDTO with minimal data.
When you get success from server on user details saving you can find corresponding user in model's user list and replace changed details there.
Tell you the truth, there's no good way of using Cairngorm. It's a crap framework.
I'm not too sure exactly what you mean by eager fetching (or what exactly is your problem), but whatever it is, it's still a request/response kind of deal and this shouldn't be a problem per say unless you're not doing something right; in which case I can't see your code.
As for frameworks, I recommend you look at RobotLegs or Parsley.
Look at the "dpHibernate" project. It implements "lazy loading" on the Flex client.

ASP.Net MVC elegant UI and ModelBinder authorization

We know that authorization's stuff is a cross cutting concern, and we do anything we could to avoid merge business logic in our views.
But I still not find an elegant way to filter UI components (e.g. widgets, form elements, tables, etc) using the current user roles without contaminate the view with business logic. same applies for model binding.
Example
Form: Product Creation
Fields:
Name
Price
Discount
Roles:
Role Administrator
Is allowed to see and modify the Name field
Is allowed to see and modify the Price field
Is allowed to see and modify the Discount
Role Administrator assistant
Is allowed to see and modify the Name
Is allowed to see and modify the Price
Fields shown in each role are different, also model binding needs to ignore the discount field for 'Administrator assistant' role.
How would you do it?
On way I could think to do this is create your own versions of the input extension methods. For example instead of TextBox you could create TextBoxRoles and define it like this:
public static MvcHtmlString TextBoxRoles(
this HtmlHelper htmlHelper,
string name,
string RolesEdit,
string RolesView
)
Then in code it would look like this:
<%= Html.TextBoxRoles("Price", "Administrator","Administrator,Assistant") %>
Then your implementation of TextBoxRoles would check the roles of the current user via User.IsInRole() to determine what should appear on the page.
Of course you would have to do this for every input extension method you use.
Since you already have both the current user and access to the authorization provider in your controllers this is an ideal responsibility for them. Using a naive implementation you might pass a collection of widgets to your view after you filtered which widgets the current user has access to. In the case of your form field, things might get hairy when you consider client side validation.
The binding part would be the most straight forward of all, having a custom binder for these special cases will do the trick specially well since it will have access to the controller context and you can grab the current user from there and bind the values according to your role definitions.
What about something like LinFu, an AOP framework? If it's crosscutting, then declare it is so and treat it as such.

Best Practices for controlling access to form fields

I have a classic 3-tier ASP.Net 3.5 web application with forms that display business objects and allow them to be edited. Controls on the form correspond to a property of the underlying business object. The user will have read/write, readonly, or no access to the various controls depending on his/her role. Very conventional stuff.
My question is: what is the object-oriented best practice for coding this? Is there anything more elegant than wrapping each control in a test for the user's role and setting its Visible and Enabled properties?
Thanks
You'll want to drive this off of data, trust me. You'll need a lot of tables to do it right, but it is so worth it in the end. Having to crack open code and edit a bunch of if-statements every time the business wants to change permissions is a killer.
You'll want a table for your main high-level types, things you probably already have business object clases for. Then a table for each status of them. Then a table for the fields of these classes. Then a table for user roles (admin, guest, etc.) Finally a table for the permissions themselves. This table will have columns for business class, status, field, user role, and then what permission they have. For permissions I would go with one field and use an enum: Hidden, ReadOnly, Editable, and Required. Required implies Editable. Anything but Hidden implies Visible. Finally put a Priority column on this table to control which permission is used when more than one might apply.
You fill out this table with various combinations of class, status, field, role, and permission. If a value is null then it applies to all possible values. So you don't need a trillion rows to cover all your bases. For example, 99% of the time, Guest users are read-only users. So you can put a single entry in the table with only the Guest role specified, everything else is null, and set it's Priority nice and high, and set the permission to Read Only. Now for all classes, all statuses, all fields, if the user is a Guest, they will have Read Only permission.
I added status to your list of concerns because in my experience, business all the time wants to constrain things by an object's status. So maybe users can edit an item's name while it is in Draft status, for example, but once it is in Posted status, the name is no longer editable. That is really common in my experience.
You'd want to bring this table into memory and store it in the app's cache, because it's not going to change very often, if ever, unless you do a whole new version.
Now the above is going to handle 90% of your needs, I suspect.
One area that will have to be handled in code, unless you want to get really fancy, is the cases where a user's permission is determined in part by the value of fields in the object itself. So say you have a Project class, which has a Project Manager class. Now the Percent Complete field of the class is basically read-only for everybody, except the Project Manager. How are you going to handle that? You'll need to provide a way to incorporate specific instances of a class into the decision making process. I do this in code.
To work properly, I have found that access levels should be in this increasing order:
NONE, VIEW, REQUIRED, EDIT.
Note that REQUIRED is NOT the top level as you may think it would be since EDIT (both populate & de-populate permission) is a greater privilege than REQUIRED (populate-only permission).
The enum would look like this:
/** NO permissions.
* Presentation: "hidden"
* Database: "no access"
*/
NONE(0),
/** VIEW permissions.
* Presentation: "read-only"
* Database: "read access"
*/
VIEW(1),
/** VIEW and POPULATE permissions.
* Presentation: "required/highlighted"
* Database: "non-null"
*/
REQUIRED(2),
/** VIEW, POPULATE, and DEPOPULATE permissions.
* Presentation: "editable"
* Database: "nullable"
*/
EDIT(3);
From the bottom layer (database constraints), create a map of fields-to-access. This map then gets updated (further restrained) at the next layer up (business rules + user permissions). Finally, the top layer (presentation rules) can then further restrain the map again if desired.
Important: The map must be wrapped so that it only allows access to be decreased with any subsequent update. Updates which attempt to increase access should just be ignored without triggering any error. This is because it should act like a voting system on what the access should look like. In essence, the subsequent layering of access levels as mentioned above can happen in any order since it will result in an access-level low-water-mark for each field once all layers have voted.
Ramifications:
1) The presentation layer CAN hide a field (set access to NONE) for a database-specified read-only (VIEW) field.
2) The presentation layer CANNOT display a field when the business rules say that the user does not have at least VIEW access.
3) The presentation layer CANNOT move a field's access up to "editable" (nullable) if the database says it's only "required" (non-nullable).
Note: The presentation layer should be made (custom display tags) to render the fields by reading the access map without the need for any "if" statements.
The same access map that is used for setting up the display can also be using during the submit validations. A generic validator can be written to read any form and its access map to ensure that all the rules have been followed.
I have often found that this is really the only real easy and understandable way to do it, as your interface needs to modify based on the information and level of editing that they can complete.
I do find typically though that depending on the needs, you can interject the "cannot edit" information by passing role information to the business level if you have plans to move to different presentation levels. but this adds complexity, and if you are only building for one interface it would most likely be overkill
For the website menus we can have different menus based on users role by using the Sitemaps. For controls like Buttons we will have to hide them using their Visible property. I think a good idea will be to create a server control (Button) and expose the Role property. This will hide the Button if the user is not in the correct role.
My first instinct for doing this in a more OO way would be to handle your roles and their implementations for this purpose (control permissions read/write/etc) is to use the abstract factory pattern for your roles. I will be happy to explain the ins and outs of what I am talking about if you'd like but there are probably 900 examples on the web. Here is one link (disclaimer: it's my blog but it does happen to talk to using abstract factory for roles specifically)
Using something like this you could then use a number of methods to display the correct controls for each of your business object properties with the correct attributes (read/write/hidden/displayed/etc).

Resources