Christian
Christian

Reputation: 19750

MVC Multi User Authentication/Security

I've been working on a web application for a company that assists them with quoting, managing inventory, and running jobs. We believe the app will be useful to other companies in the industry, but there's no way I want to roll out separate instances of the app, so we're making it multi-user (or multi-company might be a better term, as each company has multiple users).

It's built in Codeigniter (wish I had've done it in Rails, too late now though), and I've tried to follow the skinny-controller fat-model approach. I just want to make sure I do the authorisation side of things properly. When a user logs in I'd store the companyID along with the userID in the session. I'm thinking that every table that the user interfaces with should have an additional companyID field (tables accessed indirectly via relationships probably wouldn't need to store the companyID too, tell me if I'm wrong though). Retrieving data seems pretty straight forward, just have an additional where clause in AR to add the company ID to the select, eg $this->db->where('companyID', $companyID). I'm ok with this.

However, what I'd like to know is how to ensure users can only modify data within their own company (in case they send say, a delete request to a random quoteID, using firebug or a similar tool). One way I thought of is to add the same where clause above to every update and delete method in the models as well. This would technically work, but I just wanted to know whether it's the correct way to go about doing it, or if anyone had any other ideas.

Another option would be to check to see if the user's company owned the record prior to modification, but that seems like a double-up on database requests, and I don't really know if there's any benefit to doing it this way.

I'm surprised I couldn't find an answer to this question, I must be searching for the wrong terms :p. But I would appreciate any answers on this topic.

Thanks in advance,

Christian

Upvotes: 1

Views: 872

Answers (3)

Hailwood
Hailwood

Reputation: 92651

From the looks of things it looks like this might be a more API type system (as otherwise this is simply a normal user authentication system).

Simple Authentication
Anyway, the best bet I can see for an API is to have two tables, companies and users in the companies table have an companyID, and password. in the users table link each user to a company.

Then when a user makes a request have them send through the companyID and password with every request.

oauth
The next option, slightly harder to implement, and means that the other end must also setup Oauth authentication is oauth.

But, in my opinion is much nicer overall to use and is a bit more secure.

Upvotes: 1

swatkins
swatkins

Reputation: 13640

I'd say you're going about this the correct way. Keeping all of the items in the same tables will allow you to run global statistics as well as localized statistics - so I think this is the better way to go.

I would also say that it would be best to add the where clause you mention to each query (whether it's a get, update, delete. However, I'm not sure you'd want to manually go in and do that for all of your queries. I would suggest you overwrite those methods in your models to add the relevant where clauses. That way, when you call $this->model->get(), you will automatically get the where->($companyID, $userID) clause added to the query.

Upvotes: 1

stormdrain
stormdrain

Reputation: 7895

One way to do it would be with table prefixes. However, if you have a lot of tables already, duplicating them will obviously grow the size of the db rapidly. If you don't have many tables, this should scale. You can set the prefix based on user credentials. See the prefixes section of this page: http://codeigniter.com/user_guide/database/queries.html for more on working with them.

Another option is to not roll out separate instances of the application, but use separate databases. Here is a post on CI forum discussing multiple db's: http://codeigniter.com/forums/viewthread/145901/ Here again you can select the proper db based on user credentials.

The only other option I see is the one you proposed where you add an identifier to the data designating ownership. This should work, but seems kinda scary.

Upvotes: 0

Related Questions