Controlling access to data - asp.net

I keep running into cases were I want to limit access to data rather than methods.
As an example, I have a users table. An individual user's record should be visible only to themselves, the helpdesk, and the user's manager. However, only the manager can edit the user.
I can restricted view and edit methods by the above roles using the authorization attributes, but then I still need to check and see if the current user has the ability to touch the data he is requesting. This is where the authorization attribute falls short.
I'm currently considering adding an "IsAuthorized" method to all of my models to check and see check if the current user is allowed to perform the current action, but this seems tedious in general, so I wanted to see if anyone else had a centralized way of doing this.
Thanks again!!
(Currently coding everything in ASP.NET C# MVC 4.5.)

Related

How can I allow the Current User to have permissions/views tied to their Direct Reports and Manager relationships?

In a handful of circumstances, I'd like to allow the Current User to be able view a list of records filtered by Owners of each record that are Direct Reports that they manage or even by the Manager they report to via our global directory.
I'm comfortable making a new Datasource for CurrentUser in a Directory model. However, I'm tripping over myself trying to find the best way to match an Ownership (email) field from a record, with an array of the direct reports associated with the current user.
A specific example would be on the Travel Approval template. The table on the Dashboard page has a filter for "My Requests | All" and I'd love to add a third option for "Direct Report Requests".
My assumption is that I would adjust the onClick event to filter results accordingly:
widget.datasource.query.pageIndex = 1;
widget.datasource.query.filters.Owner._equals = app.user.email;
widget.datasource.query.filters.Owner._in = null;
widget.datasource.load();
updateUrlForDashboard();
That's one small example, but more importantly, I'd like to get a better understanding of how best to reference/store those additional relationships about the Current User.
Ideally, a current user is able to have greater ability to manage (approve/deny/comment on) resources tied to their Direct Reports and generate records that provide a similar level of control to the Users that Manage them.
I'm not sure if that's best handle by some use of Roles or another approach. Any advice on how best to plan out that kind of setup would be much appreciated.
funny thing ... I had the same question a couple of months ago. I think you will find Pavel's solution on this very interesting. You can find it here.

Why are hidden fields used?

I have always seen a lot of hidden fields used in web applications. I have worked with code which is written to use a lot of hidden fields and the data values from the visible fields sent back and forth to them. Though I fail to understand why the hidden fields are used. I can almost always think of ways to resolve the same problem without the use of hidden fields. How do hidden fields help in design?
Can anyone tell me what exactly is the advantage that hidden fields provide? Why are hidden fields used?
Hidden fields is just the easiest way, that is why they are used quite a bit.
Alternatives:
storing data in a session server-side (with sessionid cookie)
storing data in a transaction server-side (with transaction id as the single hidden field)
using URL path instead of hidden field query parameters where applicable
Main concerns:
the value of the hidden field cannot be trusted to not be tampered with from page to page (as opposed to server-side storage)
big data needs to be posted every time, could be a problem, and is not possible for some data (for example uploaded images)
Main advantages:
no sticky sessions that spill between pages and multiple browser windows
no server-side cleanup necessary (for expired data)
accessible to client-side scripts
Suppose you want to edit an object. Now it's helpful to put the ID into a hidden field. Of course, you must never rely on that value (i.e. make sure the user has appropriate rights upon insert/update).
Still, this is a very convenient solution. Showing the ID in a visible field (e.g. read-only text box) is possible, but irritating to the user.
Storing the ID in a session / cookie is prohibitive, because it disallows multiple opened edit windows at the same time and imposes lifetime restrictions (session timeout leads to a broken edit operation, very annoying).
Using the URL is possible, but breaks design rules, i.e. use POST when modifying data. Also, since it is visible to the user it creates uglier URLs.
Most typical use I see/use is for IDs and other things that really don't need to be on the page for any other reason than its needed at some point to be sent back to the server.
-edit, should've included more detail-
say for instance you have some object you want to update -- the UI sends back a collection of values and the server at that point may or may not know "hey this is a customer object" so you fire off a request to the server and say "hey, give me ID 7" and now you have your customer object as the system knows it. The updates are applied, validated, whatever and now your UI gets the completed result.
I guess a good excuse/argument is using linq. Try to update an object in linq without getting it from the DB first. It has no real idea that it's something it can keep track of until you get the full object.
heres one reason, convenient way of passing data between client code (javascript) and server side.
There are many useful scenarios.
One is to "store" some data on a page which should not be entered by a user. For example, store the user ID when generate a page, then this value will be auto-submitted with the form back to the server.
One other scenario is security. Add some hidden token to the page and check its existence on the server. This will help identify whether a form was submitted via the browser or by some bot which just posted to some url on your site.
It keeps things out of the URL (as in the querystring) so it keeps that clean. It also keeps things out of Session that may not necessarily need to be in there.
Other than that, I can't think of too many other benefits.
They are generally used to store state as an interaction progresses. Cookies could be used instead, but some people disable them. Could also use a single hidden field to point at server-side state, but then there are session-stickiness issues.
If you are using hidden field in the form, you are increasing the burden of form by including a new control.
If there is no need to take hidden field, you should't take it because it is not suitable on the bases of security point. using hidden field does not come under the good programming. Because it also affect the performance of application.

In the context of an asp.net website, what's the most efficient way to check whether a User has access to a particular record?

I have a webpage that you pass in an id parameter (via a querystring), which it then uses to fetch data from a database. Typically, a user would navigate to this page from another page that lists only those records that the user has access to. However, if they go directly to the page by typing in the URL in the Address Bar, they can effectively view any record they like.
Eg. If they were to type something like http://localhost/TestSite/ClientAdmin/ManageLocation.aspx?LocationID=5 into their Address Bar, they can access the database record with the LocationID equal to five - even though they shouldn't have access to it.
Now, I could solve this by doing a database check every time the page is loaded to see whether the current user has access to the record they're trying to view. However this doesn't seem very efficient given that in most cases a user won't be trying to access a record that isn't theirs. Does anyone have a better suggestion?
Thanks.
Rather then doing an extra check when the page is loaded you could use an INNER JOIN and effectively return nothing if the access rights aren't there.
If all the indexes are there it shouldn't cost very much.
You could use Page.Request.UrlReferrer to see where they've come from, but it isn't a completely safe way of achieving this.
If each user has 'their own' data, that other users don't have access to, then it sounds like you may want to look at proper multitenancy - though that is often on a per-organisation basis rather than per-user:
http://en.wikipedia.org/wiki/Multitenancy

Query String Parameters make my app at risk?

I'm writing an Asp.Net WebForms app where I am calling an edit page an passing in the data about the record to be edited using query string parameters in the URL.
Like:
http://myapp.path/QuoteItemEdit.aspx?PK=1234&DeviceType=12&Mode=Edit
On a previous page in the app, I have presented the user with a GridView of screened items he can edit based on his account privileges, and I call the edit page with these above parameter list, and the page know what to do. I do NOT do any additional checking on the target page to validate whether the user has access to the passed in PK record value as I planned to rely on the previous page to filter the list down and I would be fine.
However, it is clear the user can now type in a URL to a different PK and get access to edit that record. (Or, he may have access to Mode=View, but not Mode=Edit or Mode=Delete. Basically, I was hoping to avoid validating the record and access rights on the target page.
I have also tested the same workflow using Session variables to store PK, DeviceType, and Mode before calling the target page, and then reading them from Session in the target page. So there are no query string paramaters involved. This would take control away from the user.
So, I'm looking for feedback on these two approaches so that I choose an accepted/standard way of dealing with this, as it seems like a very common app design pattern for CRUD apps.
Agreed, you'll want to validate permissions on the target page, it's the only way to be absolutely sure. When it comes to security, redundancy isn't a bad thing. Secure your database as if you don't trust the business layer, secure your business layer as if you don't trust the UI, and secure the UI as well.
You should always validate before the real execution of the action, especially if passing the parameters by query string. For the second page that does the execution you might not need as much feedback for the user since you do not have to be nice to the user if he tries to cirumvent your security, so error handling should be a lot easier.
Passing the variables per session is acceptable but imho you should still validate the values.
We always use querystrings so records can be bookmarked easily, however always validate in both places, if you write you access control code nicely it should just be a case of re-using the existing code...
I believe the common practice is to do what you're avoiding: On the original page, you need to check to see what the user should have capabilities to do, and display their options appropriately. Then on the actual work page, you need to check the user again to verify they are allowed to be there, with access to that specific task.
From a usability standpoint, this is what the user would want (keeps it simple, allows them to bookmark certain pages, etc), and security on both pages is the only way to do this.
If you really don't want to check access rights on the target page:
You could hash the PK with the UserID and then add the hash value to the query string.
string hash = hashFunction(PK.toString() + UserID.toString());
Then you have to make sure the hash in the queryString equals the hash value calculated before loading the page.
Assuming this is an internal organization Web application.
Session variables can be manipulated as well, although not as easily. Whatever authentication you're using throughout your site, you should definitely use on your target page as well. Otherwise, you'll be open to exposing data you may not want as you have found out.
You could do the following to make your URLs a bit more secure:
-Use Guids for Primary Keys so users cant guess other record ID's
-The Mode couls be implicit: Guid = Edit, no Guid = New
and..
-Server-side validation is the only way to go.

Best way to ensure page-level security

I wish to ensure a user has access to an aspx page by 'Zone'. For example, "Financials" is a Security Zone which some users should not have access to.
The result should not involve patterns such as MVP, MVC, MVVM, etc. I'm looking for something that's light and quick to do.
To make things easier I have a base class which each aspx page derives from. What is the easiest/best way to have each page to be checked versus a security zone given the userID?
Thanks.
I've used this, whether it's the best way is seriously questionable. I have a class I derive from Page, called SecurePage. In that I usually have a cross table in a database that lists objects, such as the page, and groups/users that have access to that page. Running a stored procedure using the UserID and the Object name (Page name in this case, but can be a field, or whatever) it returns whether that user or a group that the user belongs in has access. You can check this during the page init, and if it doesn't match up, then response.redirect them or whatever you want to do.
You basically need to create a little ACL implementation. (Access Control List).
Create a acl_roles table, with all your roles (Admin, Accountant, whatever, guest) and stuff. Then link the id of it with your user table, so each user has a role_id.
Then define a acl_resources table, where you add the "zones" in your app and the minimum role they have to be to access it.
Then at the start of each script simply do check if the current user has enough privileges to be in that zone.
There are more details into this, but that is the basic idea.
Yeah, use forms or Windows authentication. You can easily lock down different parts of your site based on the authenticated user's role. Look into using locations.
Why not just use the security features such as forms authentication built into .NET? It's very easy.

Resources