I have what I consider to be a pretty basic security issue for an application designed to be run as SaaS. The following image indicates the relation between entities:
Basically users of the company creates items which every other user of the company should have access to. The question is how to best solve this in Symfony2. Using ACL seems like overkill.
Also, most of the examples I've seen seem to handle the security measures in the controller action which seems strange to me. I would prefer the controller interact with a repository which handles the security and permissions internally.
What is the best practice for this?
Your schema shows the solution in my opinion.
The simplest coding scenario I could think of is:
My user is logged in
Get the user's company
Paginate all items attached to this company
You won't have an ACE system but that would do the work according to your question.
If you want an extra layer of flexibility I'd add UserGroup entity in the middle of Company, User and Item. Item would relate to Company through UserGroup and same thing for User.
This UserGroup entity could have an extra column that holds ACE data in a JSON-encoded string so that whenever you get the group you have directly access to the group's ACEs.
One thing I learned about ACL/ACE in general is that you will have to take the right amount of time to plan your integration otherwise it will become really hard to maintain.
To answer your last question, there isn't any best practices for ACLs. Symfony2 has a very generic ACL system that might not scale well however it will fit most requirements (if not all of them). I find Symfony2 ACL/ACE system great but the performance are far from great.
If you have the chance, you can wrap Symfony ACL/ACE system with a caching layer which would be ideal. However if your host doesn't allow you to install a solution such as Memcached or Redis then you can't use this solution.
Related
The ability to add, update, and delete various entities in my application is often determined by the relationships defined between the various users involved. Here is an example:
A basic user or his supervisor can create tasks associated to the user, but only his supervisor can lock down the task so that the basic user will not longer be able to add/update/delete it. Until locked down, both individuals will be able to update the task.
What is the best approach to implement these kind of complex and advanced rules that deal with the relationship of users and the state of the entities (new, existing), as well as other things like maybe a user-defined status associated to the entity?
Thanks
What is the best approach to implement these kind of complex and advanced rules that deal with the relationship of users and the state of the entities (new, existing), as well as other things like maybe a user-defined status associated to the entity?
You want to use an authorization standard, namely XACML, the eXtensible Access Control Markup Language. XACML is:
a standard developed by OASIS, just like SAML is
a standard that focuses on fine-grained access control: access control that takes into account user information, resource information, state, and contextual information
a standard that implements the attribute-based access control (ABAC) model: the user information, resource data, and state can all be seen as attributes
a standard that uses policies and rules to structure the attributes and grant / deny access: XACML is policy-based
a standard that can be applied across multiple layers e.g. across the presntation tier, the data tier, the business tier of an MVC application
a standard that can be applied to multiple technologies and languages e.g. C# (MVC4 and more), Java, Python...
With XACML, you can easily implement relationships e.g.: an employee can approve a transaction if and only if the transaction amount < employee approval limit AND the transaction is not locked.
Where to go from here?
Check out NIST's page on ABAC.
Check out OASIS XACML's page and spec
Check out existing implementations (open-source and vendor such as the one I work for, Axiomatics.)
At a bank I worked for, we had a loan management system that allowed the entire bank hierarchy to see loans in their reporting structure. For instance, a Market exec could see the loan portfolio of all of his/her reports at once. Additionally, s/he had the ability to select from a list of all reports' (direct or indirect) names to view the portfolio of that employee.
It was complex, but we had to maintain an HR database of the reporting structure. Once we had that, we built user functions (could be done as stored procs, too, but user functions worked well in our LINQ to SQL backend) that allowed us to check whether user x supervises user y.
So, in your example, as long as you know who owns the task, and have access to a method that can be used to determine if the task owner reports to the currently-logged-in user, you should be able to easily enable/disable the "lock" button on the page.
The legwork lies in creating that reporting structure DB, and keeping it up to date!
Our requirement is something like this.
We are building a multi-tenant website in ASP.NET MVC, and each customer should be able to create their own users as per predefined user roles.
We are thinking about to create a schema for few tables which would be common for customers. So customer can login to system according to their schema logins and we need not to alter any queries to serve all of them.
We are referring http://msdn.microsoft.com/en-us/library/aa479086.aspx Shared Database, Separate Schemas.
Can someone suggest on following
1. After creating schema how to authorize user against a particular schema
2. Is this possible that without any changes in queries db can serve multi-tenants
Thanks in advance
Anil
After much research, I can say that, although it takes more development up front and more checks along the way, shared database and shared schema is the way to go. It puts a little bit of limits on how easily you can cater to a client's specific needs, but from my point of view SAAS isn't about catering to a single client's weird needs. It's about catering to the majority of clients. Not that it's a SAAS but take iPhone as an example. It was built to cater to the masses. Rather than focusing on doing everything it's built to be one-size fits all just by its simplicity. This doesn't help your case when it comes to authoriztion but it'll save you dev hours in the long run.
If you are asking this in the context of SQL Server authentication/authorization mechanism, i can asnwer this question with saying that every user has a default schema which helps query engine to find out required object in the database.
SQL Query Engine will look at the user's default schema first to find the required object (table). If it founds the object in user's schema then use it, otherwise goes to system default schema (dbo) to find it.
Check this article's How to Refer to Objects section to find out how it works. The article also has some information about security concepts related to schemas.
We are currently transitioning our website to Drupal 6.x from a non Drupal source. One of the first issues we need to deal with is that of authentication. We have a central database where we keep member information. We will create a module to authenticate against this database however a question of whether or not to create users in the drupal is needed.
I'm worried that if we do not add user to the user tables and have our module keep sync that with the other database, then we will not be able to take advantage of other modules that may use the user module
My colleague on the other hand believes that this is not an issue we can add all necessary attributes to the global $user at authentication with our module.
Is there a standard way of dealing with this problem?
Thanks!
David
Look at the LDAP_integration module, they do something similar. When logging in and a local user cannot be loaded, a user is searched for in another application and when user&pass are equal, the user is copied in the Drupal usertable.
If you want any Drupal functionality (read: core and modules) to be associated with that user account, then you will need to use that user table.
This is especially true for anything node-related, so if you want people to be able to create nodes with referenced data you will need it. uids are stored in the nodes table in order to show who authored the node. Storing a uid in the nodes table with a something that doesn't exist as a relational key to somewhere else will only return an empty object. For instance, if a person wants to see the author of X node they will get an empty user object. Keep it. There's no sense in working harder just to remove it. Besides, you can store as little or as much as you want in the user object for each account.
I'd also suggest looking at the LDAP module. I was able to use it as a jumping in point to interface with a custom WSAPI authentication method for an external database that we have at my company.
Do you need to have both sites running in parallel? If not, then you don't need to sync the user tables. A conversion will be enough then.
Are there any alternatives\mods to .net Membership?
I find it quite restrictive;
Cant change Username, easily. You have to create a new user and copy the fields, but then you lose the primary key OR you have to edit the user table directly yourself.
Additional profile fields are stored together as one blob.
ASP.Net membership uses a provider model. That means you are completely free to implement your own membership provider, or even inherit from and extend an existing provider, as long as you follow the provider contract.
Plus one for asking about existing alternatives rather than trying to build something new yourself, though.
I'll go ahead and list my alternative here. I've rolled my own authentication library, and I think it's awesome enough to be publicly released... So I did. It's designed to stay out of your way and overall, it's pretty minimalistic. I don't provide a lot of out of the box user controls, but on most websites I've seen those built-in user controls are never used. So instead of trying to make yet more flexible user controls, I decided instead to make it brain-dead simple to create your own login controls and such.
The project is called Fast, Secure, and Concise Authentication, or FSCAuth for short. It is BSD licensed. You can download it over at Binpress or at Bitbucket
It's flexible "UserStore" model(the Form's equivalent of provider) enables you to form your database anyway you want. It can support plain text files, XML, MongoDB, Sql Server, and anywhere in-between.
Here's a list of things where I think it particularly excels over Forms Authentication:
Stateless Authentication System. There is no requirement to keep track of user sessions in either the database or memory. This makes it trivial to scale up to multiple servers requiring few(if any) changes to your authentication code
Use anything as a Unique ID for each user. That's right, no more GUIDs! Anything that will fit in a string is fair game
HTTP Basic Authentication baked in. You can enable Basic Authentication just on pages you want(or globally) and you can make the same calls as if they were using the typical cookie-based authentication
Hard to make insecure. Because of how it works and I leave as little core-code as possible to the end user for actually doing authentication, it's extremely secure and will stay that way unless you just really try to break it. I handle cookies, HTTP Basic Auth, and all hashing. You just give FSCAuth a database to put it in.
BCrypt support for hashes is trivial. How to do it.. In Forms Authentication it is almost not possible
I like it :)
Of course it's also lacking, and to be fair I'll include a few things that are lacking
Authenticating static files in IIS 6 isn't possible(yet)
There is no brute-force prevention(yet). This means that you'll need to make sure the same person isn't trying to hit your login page 200 times in 2 seconds.
It's not built into ASP.Net
No Windows or Passport authentication (with no plans to ever add)
As the ASP.NET membership model is built around Providers, there are a number of alternatives available.
By default, users have a ProviderUserKey, which is a GUID, and that's the Primary key of the database, so you should be able to write something to change their username if you want.
In terms of the profile, yes, the default blob is fairly annoying. You could take a look at the SQL Table Profile Provider which maps profiles on to tables, or fairly quickly roll your own.
As for the Profile there are a couple of alternatives out there. These two use either a table or let you call a stored procedure. Of course you can also implement your own. I personally got tired of using the Profile Providers, and found that dealing with the profile in my code was easier to control and contain.
As for the other issues, you can also implement your own provider. Microsoft released the source code to the SQL Providers so it can give you a starting point.
As far as changing the username goes, that can easily be accomplished by using the CreateNewUser() method and filling in the appropriate fields based on the current User, and then deleting the current user.
Profile fields are not part of the .NET Membership Provider model, but part of the Profile Provider. This is a highly debated topic and for most production machines, the correct way to go is to drop-in a better profile provider solution, such as this Table Profile Provider, which stores profile fields as you'd expect rather than as a memory-hogging blob. Alternatively, you can easily roll your own profile provider, check out the instructions here.
There are certainly .NET Membership alternatives, but most are buggy or have a small featureset. It really sucks to develop on top of one for two months and then realize it won't support all the functionality you need. .NET Membership is a proven solution and that's why it is used so often.
I am looking for a best practice for End to End Authentication for internal Web Applications to the Database layer.
The most common scenario I have seen is to use a single SQL account with the permissions set to what is required by the application. This account is used by all application calls. Then when people require access over the database via query tools or such a separate Group is created with the query access and people are given access to that group.
The other scenario I have seen is to use complete Windows Authentication End to End. So the users themselves are added to groups which have all the permissions set so the user is able to update and change outside the parameters of the application. This normally involves securing people down to the appropriate stored procedures so they aren't updating the tables directly.
The first scenario seems relatively easily to maintain but raises concerns if there is a security hole in the application then the whole database is compromised.
The second scenario seems more secure but has the opposite concern of having to much business logic in stored procedures on the database. This seems to limit the use of the some really cool technologies like Nhibernate and LINQ. However in this day and age where people can use data in so many different ways we don't foresee e.g. mash-ups etc is this the best approach.
Dale - That's it exactly. If you want to provide access to the underlying data store to those users then do it via services. And in my experience, it is those experienced computer users coming out of Uni/College that damage things the most. As the saying goes, they know just enough to be dangerous.
If they want to automate part of their job, and they can display they have the requisite knowledge, then go ahead, grant their domain account access to the backend. That way anything they do via their little VBA automation is tied to their account and you know exactly who to go look at when the data gets hosed.
My basic point is that the database is the proverbial holy grail of the application. You want as few fingers in that particular pie as possible.
As a consultant, whenever I hear that someone has allowed normal users into the database, my eyes light up because I know it's going to end up being a big paycheck for me when I get called to fix it.
Personally, I don't want normal end users in the database. For an intranet application (especially one which resides on a Domain) I would provide a single account for application access to the database which only has those rights which are needed for the application to function.
Access to the application would then be controlled via the user's domain account (turn off anonymous access in IIS, etc.).
IF a user needs, and can justify, direct access to the database, then their domain account would be given access to the database, and they can log into the DBMS using the appropriate tools.
I've been responsible for developing several internal web applications over the past year.
Our solution was using Windows Authentication (Active Directory or LDAP).
Our purpose was merely to allow a simple login using an existing company ID/password. We also wanted to make sure that the existing department would still be responsible for verifying and managing access permissions.
While I can't answer the argument concerning Nhibernate or LINQ, unless you have a specific killer feature these things can implement, Active Directory or LDAP are simple enough to implement and maintain that it's worth trying.
I agree with Stephen Wrighton. Domain security is the way to go. If you would like to use mashups and what-not, you can expose parts of the database via a machine-readable RESTful interface. SubSonic has one built in.
Stephen - Keeping normal end users out of the database is nice but I am wondering if in this day and age with so many experienced computer users coming out of University / College if this the right path. If someone wants to automate part of their job which includes a VBA update to a database which I allow them to do via the normal application are we losing gains by restricting their access in this way.
I guess the other path implied here is you could open up the Application via services and then secure those services via groups and still keep the users separated from the database.
Then via delegation you can allow departments to control access to their own accounts via the groups as per Jonathan's post.