In a windows forms payroll application employing MVP pattern (for a small scale client) I'm planing user permission handling as follows.(Roll based)
NOTE : System could be simultaneously used by few users (maximum 3) and the database is at the server side.
User Tables in the database.
USER (user_id[pk], name, access_level, status)
PERMISSION (permission_id[pk], permission_detail)
USER_PERMISSION (user_id[pk][fk], permission_id[pk][fk])
I would maintain user list in USER table and permission list in PERMISSION table (permission details are the accessible module names). Intermediate table USER_PERMISSION would map the users with the permissions. UESR and PERMISSION tables have 1:M relationships with USER_PERMISSION table.
When an user login to the system, first the system will validate the user and if its valid then the home screen will be shown and the logged user's ID will be hold in a global variable (accessible to all presenter classes) . When the user try to access a specific module, the system will read that global variable to find the current user's ID and then it will look in the USER_PERMISSION table whether there is an entry relevant to that user id and the module name in which the user is trying to login. If there is and entry, then the user will be given the access to that particular module.
When user log off the variable holding the current user id will be cleared.
In this approach is it okay to hold the current user's ID in application memory? or should be written to a local file?
Modifications to the data in the tables should be tracked and in this purpose should I maintain a separate column on each table (ones should be monitored) to hold the ID of the user who is modifying the record?
EDIT:
Can we use SQL-SERVER user rolls/ logins in this purpose? and can this user action login stuff be handed over to SQL-SERVER?
When controlling Read/Write permissions in Forms, the respective Presenter handle the logic and set the properties in the View (properties like IsModifyAllowed{get;set;}, IsDeleteAllowed{get;set;} etc.) according to the current users permissions. So that the View could handle the rest of the things by enabling / disabling controllers in the View.
In this approach should the every Model have a matching property like in the view(in this case IsModifyAllowed{get; set;} etc. )?
What is the most widely used approach in this case?
What you have described in your first part of the question is pretty common, although it's not actually Role based, it's permission based.
It's not a perfect solution, although no security mechanism really is. But it's pretty simple and works.
To answer your questions.
There shouldn't be a problem with holding the id in memory, so long as we're not talking about government level security here, and there is no real concern about people breaking into the machines and trying to gain access, in which case there are probably much bigger fish to fry. Storing it in a file may actually make it less secure, and you would eventually have to read it into memory at some point anyways.
Tracking changes can be simple or complex, depending on how you want to do it. You can add a last modified field, but this will only track the most recent change. To be safe, you need an audit table that tracks all changes and keeps historical versions of the data. It's probably a good idea to do this audit table with a trigger so that your application code doesn't have to remember to do it.
Yes, you can use SQL server logins and roles, but this probably won't make things easier or less complex. With your model, you're controlling access to modules via a permissions table. Using SQL Server Roles, you would have to control access via data, and react to exceptions thrown for not being able to access things, or query the database for roles and have to do things in tables anyways. If you have Windows domain, you might want to consider using Active Directory instead.
I don't completely follow what you're saying about Views and Model properties, because you haven't adequately explained your models.
There is no "most widely used approach", everyone does it differently. Although there are a number of things people tend to do. Microsoft offers a number of approaches, for instance they have what's known as the Composite UI Application Block and Authorization Manager. You can read about an interesting impelementation here: Granular Role Based Security. Jesse Liberty offers another take Here
In short, this is something you will have to work out yourself, because there are literally thousands of ways people have done this (if not millions). Do some research, and try to come up with what works best in your situation.
Related
I'm having an issue regarding the security of an application that I'm building... It's a wrapper for a crystal report viewer that provides users with some additional functionality.
There are many internal users with the ability to create/modify Crystal Reports. I've done some tests, and for an application that deals so intimately with connecting to various data sources, it doesn't seem to care the least bit about doing so safely. There is nothing stopping me from modifying an existing crystal report that everyone trusts to make it into something malicious and harmful. All it takes is an added command table with the following sql:
DELETE FROM tbl_Employees; SELECT FROM tbl_Employees;
In fact, you can do anything in a crystal report that the user has permissions to do... so long as it ends with a select. Which leads me to my question: Is there any way for me to ensure that my application limits any connections to our sql server to just selects? I can't temporarily modify user credentials, and I can't use a single read only account because I still need to limit the user to their normal permissions (i.e. which databases they can query).
I'm not very hopeful, as nothing that I've read has led me to believe that I can restrict connections in such a manner.
On the other hand, most of the people making the reports could take a much more direct approach to destroying our data, if they were so inclined... but I hardly think that that is a good excuse not to do my best to ensure that my application is as safe as I can make it. I just can't seem to find any viable answers.
You should use a read-only account for reporting purposes--no exceptions! Give the account access to SELECT rights to tables and views and EXEC rights functions (exposed via synonyms). Avoid procedures, if possible--they are usually unnecessary and you may inadvertently give users access to procedures that modify the database (an experience a client of mine encountered).
** edit **
I guess it depends also on how the sensitive data is represented.
You would add a row-level filter to the record-selection formula when the report is run.
If the sensitive data is contained in a small number of tables, you could use role-based security (user added to group; roles assigned to group).
If you are using BusinessObjects Enterprise, you could use a Universe to control data security. BusinessViews are also an option; they are the original (before BusinessObjects and SAP) semantic layer that supports dynamic/cascading parameters, but they have been slated for obsolescence.
Ok, I'm putting this as an answer because I still can't post global comments, but this is an idea that can help you in some way (i hope).
I don't have lots of experience in SQL Server as I do in Oracle DBs. In Oracle DBs, for each user you have their own space. Each user can only read and modify DB objects (tables and other things) that are within its space (Schema), no exceptions. Then you can grant access for each user to a specific object outside his own schema, and this is a qualified access (like "read-only", "just update", etc). To make it easier to maintain those grants, you can create roles, which are basically a named group of grants that can be assigned to a specific user.
Ok, I'm pretty sure that nothing out of this is new for you, but my point is: to acomplish what you're looking for, in an Oracle environment, you could use DB users for each user and control the access to information (tables) through that (very secure) controls.
I'm pretty sure that in SQL Server, aside from minor differences, you could do the same kind of strategy. Hope this leads you to some ideas on solving that...
I'm going to make a small application for a business that will be used locally for scanning, and storing documents in a database located on the local machine or on a machine located in the same LAN.
I could create a table called Users with username and password and according to the usertype ID show a form, or another form. But I'm more interested in the recommended approach by seasoned programmers.
Any advice?
Edit: I'm looking for something that will be secure enough, but also extensible enough.
If it's just a simple application, don't use a spaceship to cross the road.
Create the following DB schema:
Users : username and hashed password
Roles : RoleName, RoleID, RoleStrength(int)
RolesMembership : Rolemembership table that contains userid and roleid to allow for future multiple membership.
When setting up roles, give them a numeric weight. ie: Admins = 1000, Power-users = 500, guests = 10. This way, on your forms, you can say, if user level is 500 or above, set full view, otherwise, view only or no access.
Better yet, abstract it out with a security class with methods like IsPowerUser, or IsAdmin.
It's simple, readable and reusable.
Even I cannot consider myself "seasoned", I would give my answer since I'm facing the same problem in these weeks.
I would define a permission mask in order to identify allowed operations, associate it to role groups, and then associate users to the groups. More complete is the permission mask, more granularity is allowed in the group definition.
In this way there is one permission definition for multiple users, which is better than define the role using a per-user type basis, since the permission mask can be modified and extended.
More complex schemes could be possible, which could allow per-user permission overriding group permission, or hierarchy permission masks in order to define supervisor users able to manage group permissions.
The application of these models depends by the required scalability and by the number of users of the system.
I could create a table called Users
with username and password and
according to the usertype ID show a
form, or another form.
Sounds like a reasonable way to go to me. Just remember to hash the passwords.
I would also componentize the common controls in the forms, so you can reuse the common parts.
If you are using Visual Studio, I would just use the built in Membership providers. That would take care of your database and everything automatically. No need to reinvent the wheel.
Although orientated towards ASP.NET, I'd thoroughly recommend checking out this article: https://web.archive.org/web/20211020202857/http://www.4guysfromrolla.com/articles/120705-1.aspx
You can use the in-built Membership and Roles objects (even in a desktop application) to define your own schemas of privilege. Using this feature takes the hassle out of creating your own database entries for the Users (and Roles) tables, while also handling password hashing for you (leading to more secure applications).
Lastly, official MSDN articles you might want to read:
On "Membership": http://msdn.microsoft.com/en-us/library/yh26yfzy.aspx
On "Roles": http://msdn.microsoft.com/en-us/library/ff647401.aspx
I have a multi-user ASP.NET MVC application. The users are not supposed to see or do anything with each other's data.
One of my controller actions is the obligatory POST to /Edit to edit a record (e.g. a contact). Now here is my problem: What if somebody forges a simple POST to /Edit (which automatically model-binds to my contact class) and edits somebody else's information? As each record is identified by Id, all that would have to be done is make a fake POST with Id XXX and then record # XXX would be overwritten with whatever the attacker supplied. How can I stop this?
The only thing I thought of is fetching the original instance every time first from the DB, check that it is in fact within the user's scope of editable objects (the ones he'd usually see to edit) and only if that check passes to proceed with UpdateModel and committing the update changes.
Is there a better way?
Edit: This is not a Cross Site/CSRF attack. Another logged in user can do this.
Authorization for the view/page and authorization for the particular object are really two separate concepts. The best approach is problem to use an Authorize attribute in conjunction with the ASP.NET roles system to either grant or deny access to a given page. Once you have verified that the user has access to the page, then you can verify whether he has the permission he is requesting for the object on which he is requesting it. I use this approach in my application, and it works great. By using the Authorize filter first, it significantly improves performance since the actual object permission checking is a much heavier operation.
Also, I use a home brewed rules system to actually set and determine whether the user has access to the object. For example, in my system, administrators have full access to every object. (That's a rule.) The user who creates the objects has full access to the object (also specified by a rule). Additionally, a user's manager has full access to every thing his employees have access to (again specified by a rule.) My application then evaluates the object to see if any of the rules apply--starting with the lest complex rules first and then moving on to the more complex rules last. If any rule is positive, I discontinue rule evaluation and exit the function.
What you could do is exclude the ID in the model binding with this syntax:
public ActionResult Edit([Bind(Exclude="Id")] User userToEdit)
and then fetch the ID from the current logged in user instead, so that it is only the logged in user that can edit his own items and noone elses.
Loading the original record first and checking the owner sounds like a good approach to me. Alternatively you could add a hidden field containing the record ID and cryptrographically sign that field to make sure it can't be changed, or take the record ID, hash it using the user ID as a salt and check that (assuming you're using the membership providers you should use the provider unique ID, not the login name)
This question reminded me of an article that covers a similar issue (in light of URL manipulation attacks) that i had bookmarked. They deal with an authenticated user messing with the data of another user. You might find it useful:
link text
Edit: This link should be correct:
Prevent URL manipulation attacks
I am looking into building an authentication in my ASP.NET application with the following requirements.
A user has exactly one Role (i.e. Admin, SalesManager, Sales, ....)
A role has a set of permissions to CRUD access a subset of existing objects. I.e.
"Sales has CREAD, READ, WRITE permission on object type "Products" but not DELETE"
Somehow I like the permissions to be in a hierarchy with inheritance so that I for i.e. Admin don't need to specify all available objects.
The system must quickly be able to answer the question "Does user X have permission to do Y to object Z"
All database managed (MSSQL), implemented in C#/ASP.NET
I would like to get feedback on these requirements? Any ideas how to implement this using ASP.NET framework(as much as possible)? (However, I'm also interested to know how this can be achieved without Memberships)
I think what you need to do here is implement a set of permissions query methods in either your business objects or your controller. Examples: CanRead(), CanEdit(), CanDelete()
When the page renders, it needs to query the business object and determine the users authorized capabilities and enable or disable functionality based on this information. The business object can, in turn, use Roles or additional database queries to determine the active user's permissions.
I can't think of a way to declaratively define these permissions centrally. They need to be distributed into the implementation of the functions. If you want do improve the design, however, you could use dependency injection to insert authorizers into your business objects and thus keep the implementations separate.
There's some code that uses this model in Rocky Lhotka's book. The new version isn't in Google yet.
I think one of the best implementations that I think will fulfill your requirements is documented here. The only issue is that this hooks into NHibernate, but you can use this as a template to create your own permissions implementation and simply hook into your own event model rather than that of NHibernates Interceptors.
I am working on such a system myself and will blog it once I am happy with it.
The membership API provided since ASP.NET 2.0 should suit your requirements well. The only thing I'm afraid it doesn't directly support is hierarchical roles. However you can easily use normal role based security with another manually written hierarchical roles table to achieve the required things.
You can read on how to set up ASP.NET Membership here: http://msdn.microsoft.com/en-us/library/yh26yfzy.aspx
It allows you to group folders / pages etc into Groups / Users. I think you will find this sufficient!
The hiarchy is easily managed by extending the generated databases and procedures.
I would build the user/role relationship so users can have more than 1 role. I see a 1-1 relationship and I get nervous because I know that even if we don't see a need for it now, someone is someday going to want someone to be both a Sales user and a Customer Service user.
In our customer system, we use roles to layer on stuff like "delinquentCustomer." That way, the original permissions are still valid--as soon as they pay their bill. Worth considering this approach.
I've got an Active Directory synchronization tool (.NET 2.0 / C#) written as a Windows Service that I've been working on for a while and have recently been tasked with adding the ability to drive events based on changes in group membership. The basic scenario is that users are synchronized with a security database and, when group membership changes, the users need to have their access rights changed (ie. if I am now a member of "IT Staff" then I should automatically receive access to the server room, if I am removed from that group then I should automatically lose access to the server room).
The problem is that when doing a DirectorySynchronization against groups you receive back the group that has had a member added/removed, and from there when you grab the members list you get back the list of all members in that group currently not just the members that have been added or removed. This leads me to quite an efficiency problem - that being that in order to know if a user has been added or removed I will have to keep locally a list of each group and all members and compare that against the current list to see who has been added (not in local list), and who has been deleted (in local list, not in current members list).
I'm debating just storing the group membership details in a DataSet in memory and writing to disk each time I've processed new membership changes. That way if the service stops/crashes or the machine is rebooted I can still get to the current state of the Active Directory within the security database by comparing the last information on disk to that from the current group membership list. However, this seems terrible inefficient - running through every member in the group to compare against what is in the dataset and then writing out changes to disk each time there are changes to the list.
Has anyone dealt with this scenario before? Is there some way that I haven't found to retrieve only a delta of group members? What would you do in this situation to ensure that you never miss any changes while taking the smallest performance hit possible?
Edit: The AD might contain 500 users, it might contain 200,000 users - it depends on the customer, and on top of that how many groups the average user is a member of
You can set up auditing for the success of account modifications in group policy editor
You may then monitor security log for entries and handle log entries on account modifications.
E.g.
EventLog myLog = new EventLog("Security");
// set event handler
myLog.EntryWritten += new EntryWrittenEventHandler(OnEntryWritten);
myLog.EnableRaisingEvents = true;
Make sure that you have privileges to acces Security event log
http://support.microsoft.com/kb/323076
I'd say it depends on how many active directory objects you need to keep track of. If it's a small number (less than 1000 users) you can probably serialize your state data to disk with little noticable performance hit. If you're dealing with a very large number of objects it might be more efficient to create a simple persistence schema in something like SQL Express and use that.
You know there are products which help you with directory synchronization and user provisioning (google those terms)? Not invented here and all that, and you may have to justify the investment in the current climate, but developing and maintaining code for which there already is a commercial solution is not, let us say, always the most cost-effective way in the long run.
Not all of the support eventing/provisioning, but they do support tracking changes and distributing them: it's not a big deal creating eventing solutions on top of those capabilities.
Microsoft has the Identity Integration Server (MISS) which is being repackaged as part of Identity Lifecycle Manager. It was originally built on a more general meta/master data management product, but is workable. IBM has the Tivoli Directory Integrator (but you need to keep up with the biyearly name changes!). Oracle has an Oracle Identity Manager, and Sun an Identity Manager. Most of these are leading products bought by the major players to fill a gap in their portfolios.
Of course, these are enterprise-class products, meaning large & expensive, but generally pretty future-safe and extensible. If you don't need their full strength (yet!), you'll need to look at storing a copy for yourself. In that case, have you considered storing your replica of the last known AD tree using AD LDS (formerly AD/AM)? It's not in an optimum format for comparing differences, but a directory database will scale reasonably well, even the lightweight kind.