PHP - Good practice to apply multi-level PHP User Authorization - php

Given a website site has different web pages that can only be accessed by different group of users. Say guest users can only access welcome page/search page, while, administrator users can access pages that update the DB, etc.
I have little experience on this field and would like to adopt some best practice with clean/simple/secure implementation.
If possible, I would like to see some concrete examples/tutorials, even a book resource.
Thank you for your helps

I have found that many applications available online (Wordpress, Joomla, and many other), are very poorly organized in this field (poorer than what I do, in any case).
Take a look at how it's done for MVC frameworks like Zend Framework, CakePHP, Symfony. MVC is mostly used for bigger projects that tend to be much more organized, so I am betting that they have worked a lot on authentication too.
In 2 words, for this to work properly, all your page generation classes (I advise the use of OOP) must be derived from a parent class, which will hold access control methods. Or you could have a class with static functions for access control. Before any action, simply call these functions to check whether the user has access to this functionality. Functionality can be grouped into Classes, with many Methods (in MVC - Controllers and Actions). You can store access information in the database as follows: groupID, Class, Method, Permission, where permission could be a boolean Grant or Deny. To promote speed, extract all user's permissions at first query, store it in an array or object, so as not to generate a query for each permission verification in the user request, but parse the saved data instead..

Each user can have a role or roles in your application / website. Imagine you have an application where some people can edit users and others can insert tasks while others can solve the tasks. Create three roles: user managers, task assigners and task solvers.
Then give users their roles.
Some people call roles groups. You group people to give them permissions. I prefer calling it role because user acts as HR manager or website publisher etc.
This is just a simple example, it's always based on requirements you have. There can be team-based permissions, department-based permissions etc.
http://en.wikipedia.org/wiki/Role-based_access_control
Personally, I have an application broken down to modules. Each module has objects and these objects have actions. Example: user.department.list = in module user, there's an object department and action list (departments). When you create role or group, assign these permissions to that role (group) and users. For role User managers, there're permissions user.user.list, user.user.edit, user.department.list, user.department.edit. After you authenticate a user (to know who's he) load roles he's assigned to. Each page (controller) or each method can check user's permissions - is this user permitted to list departments?

Related

Laravel multiple user types with groups

I am currently building a website with the following user types:
customers
caregivers
partners
agent/mediator
system user (<- special case, I'll talk to you in a moment)
Each user type should only be allowed to do certain things.
However, the system users are somewhat different.
These should be able to be divided into groups, and these groups should also have different rights.
My customer should be able to create/edit these groups including the assignment of given rights. However, it should not be possible to edit the other user types.
I have already seen this ACL packages (https://github.com/spatie/laravel-permission and https://github.com/JosephSilber/bouncer).
But I don't think they support that.
I have also thought of the following approach: There is no user type "system user", but the users are assigned the type of group, and in the code, I check if this type is "customer","caregiver","partner" and "agent". If this is not the case, the user is automatically a system user.
Is there perhaps an open source project that has such a similar approach? I'm currently having a hard time with all the controller classes at the moment (have now merged them into a single user controller and have the $type in the route and a factory class return the right model to me, and then call up a factory again to return the respective service class <- feels totally wrong and badly implemented).
Currently, Joseph Silber is building multi-tenancy for Bouncer. I think that will fit your needs, but it's not released yet for the time I'm writing this.
Also, it's practically 100% sure that you will need to extend a package like that or fork it to adapt to your needs. Looks like a very specific code that will need modifications.

Mixed RBAC design - fine or bad?

Introduction
I am designing my application role-permission-based access system.
In my system I have the following roles:
Root
Office manager
Auditor
Customer
Worker
For example, lets view the users relations with 'task' entity.
Worker and Customer are quite special roles, they will have almost read-only access to their own tasks.
Workers will see only few properties of the 'task' object.
Depending on system business rules, in some cases they will be able to update one or two properties.
Root user can do everything, it can create, update, read, delete 'tasks'.
Office manager can list, update and create 'tasks'.
Auditor can only list tasks.
Root, Auditor and Office manager will have access to same (full) set of 'task' entity properties.
This three user types will access system via same management interface (web app module).
Customers will access system via separate role-oriented module (customer module), functionality is too specific.
Workers - too (worker module).
So, using the described example, we can say that we can create the following permissions for Root, Auditor and Office manager:
LIST_TASKS
CREATE_TASKS
UPDATE_TASKS
DELETE_TASKS
This will work for them, but not for Customer and Worker.
For Worker we could do:
LIST_WORKER_OWN_TASKS
UPDATE_WORKER_TASK_STATUS
... and so on.
But this makes quite low sense, as for me.
Noone else but Worker will use this permissions.
Also, the conditions when Worker will be able to edit certain properties of 'task' entity can not be described using permissions.
Summary
So, I make a conclusion, that I need a mixed access control system.
Customers and Workers will be roles without any permissions.
Root, Auditor and Office manager will be roles with set of permissions binded to each role.
Finally , we can call such mechanism mixed permissions-and-role based access system.
Question
Is it a normal to have such design?
Am I thinking wrong way?
Or it is better to describe Customer and Worker logic (as much as possible) using very detailed list of permissions?
I likely wouldn't do something like this just because it seems to be not maintainable over a long term.
Within an organization, roles are created for various job functions.
The permissions to perform certain operations are assigned to specific
roles. Members or staff (or other system users) are assigned
particular roles, and through those role assignments acquire the
computer permissions to perform particular computer-system functions.
Since users are not assigned permissions directly, but only acquire
them through their role (or roles), management of individual user
rights becomes a matter of simply assigning appropriate roles to the
user's account; this simplifies common operations, such as adding a
user, or changing a user's department.
Reference: https://en.wikipedia.org/wiki/Role-based_access_control
You could also implement ACL (Access control lists)
An access control list (ACL), with respect to a computer file system,
is a list of permissions attached to an object. An ACL specifies which
users or system processes are granted access to objects, as well as
what operations are allowed on given objects.[1] Each entry in a
typical ACL specifies a subject and an operation. For instance, if a
file object has an ACL that contains (Alice: read,write; Bob: read),
this would give Alice permission to read and write the file and Bob to
only read it.
I usually prefer ACL implementations because they give a finer grain of control.
Reference: https://en.wikipedia.org/wiki/Access_control_list
After looking at your thought, it looks like you are wanting to actually implement ACLs. Loading each users permission through a template. Of course you can always implement both but that is usually just so much overkill and you more-or-less have the security model of the Windows operating system afterwards.

Is there a solution to centralize access control (to entities) based on ownership and other user-document relations

Lets say i have a number of types of documents in my system. I want to restrict access to them based on three aspects: user roles, ownership and relevance of user to the object. So for example ROLE_DOCUMENTTYPE1READ will grant user a right to read document (other roles such as ROLE_DOCUMENTTYP1WRITE will grant RW rights). Presence of connection to the document (if document has user in his 1:M related_users field) gives user right to add comments to document. And if user is owner of the object he can edit it entirely.
I can easily implement it in controller or even create a trait or something like this, but it would be too ugly and also tedious because there will be lots of entities and actions upon them, not only regular CRUD, but also additional one's that change certain fields. I want to know how usually such things should be done. Maybe there are some architectural patterns that help in this situation? Right now, as i already said, i'm going to check in every action if user is related to entity or if he is even its owner or has said roles.
You can take a look at the JMSSecurityExtraBundle and the Expression-based Authorization Language. They allow to perform complex access decision checks, and because they are compiled down to raw PHP, they are much faster than the built-in voters.

A more simple approach to role-based access control (RBAC)?

I'm having a difficult time grasping the code behind role-based access control (RBAC). I'm trying to use a "bundle" with the Laravel framework but it only seems to be complicating things more.
What I need for my specific application is three roles. The first and most basic role is just to allow users to be able log into my application, manage their account, and save "favorites" and "deals". The second role I need is to allow store owners to be able to log in and create accounts and deals. The third role is basically an admin role so I can go in and remove unwanted content if need be.
Would there be any anticipated problems with just simply adding an int field to the user table called something like "role"? If a user's role is 0, then they have basic privileges and can't access the admin and owner area of the site; a 1 would indicate the user has an owner role, etc. I would simply check the user's role every time a request was made.
Would this be a reasonable, secure solution, or could I potentially run into problems using this approach?
Using RBAC would give you more flexibility when it comes to managing access to your application's functionality. Each user can be assigned with multiple roles, tasks and operations; each role can consist of multiple tasks and each tasks can consist of multiple operations.
If your application only demands 3 roles, basic, owner and admin, I think it's fine to just add an indicator in your user table. However, if you need to grant certain users access to certain operations, you would need a new number for every operation you want to differentiate access controls. Hence, using that approach would make it difficult to separate permissions based on functionality.
An alternative solution is to use ACL, which I believe it's easier to implement but probably a bit more difficult to manage. You can learn the difference between ACL and RBAC here.

How do I handle user roles effectively?

That's kinda vague so here's the meaty stuff:
I have seen authentication systems that do one of the following
have a separate role table for each roles, and a separate permissions table, all users in one table
have a separate table for administrators
there's a lot that I have missed, I know. But what I'm trying to really ask is:
How should I design my database in a website that I have a lot of kinds of users and each with different access?
How will I make it so that my script is flexible enough if I decide to add another type of user with another type of permissions?
I currently have a User class and am planning to make my Administrator class which extends that User class. Or is that a bit of an overkill when I can have them all in a single class and just assign necessary permissions?
you can have tables -
user (user_id, name ...)
permission (perm_id, name, desc)
role (role_id, title)
user_role (user_id, role_id)
user_permission (user_id, perm_id)
role_permission (role_id, perm_id)
This way you can have as many roles in the system as you require, and you have both role level permissions, user level permissions.
you can add an additional level of abstraction. basically you add a table in your database to manage user groups, and assign group permissions to those groups. different users can have multiple groups.
this way you can quickly change permissions to a predefined set of rules, without needing to change every user separately. you can also change the permissions for a group of users at once
I think you need to think about several concepts here. The first would be an access control list (ACL) and then second would be authentication.
In an ACL, you define resources, which are objects that you want to restrict access to and roles, which are objects that may request access to a resource.
The way I implement my ACL, is using Zend_Acl. I have a table called user_roles
user_roles('user_role_id', 'name', 'permissions', 'parent_role_id')`
I also have a table called user_role_maps that maps a user's ID to a user role ID. (You could just have this as a column on the user table, but that just depends on how you feel about normalisation ;-) .) I can then construct my Zend_Acl object from this table and then, when a user is authenticated, I can determine which resources they have permission to and what actions they can perform on a resource. (A resource implements Zend_Acl_Resource_Interface so it is identifiable by Zend_Acl as a resource.
As for authentication, this is a simpler concept (in my opinion), you've probably already figured out some form of token matching authentication system yourself. The crucial aspect is using the authenticated user's ID to determine their role. The Zend Framework also provides a package for this in Zend_Auth.
I've used a lot of Zend Framework recommendations here, the reason for this is that their packages have very few dependencies on other packages, making it quite simple to plug components in. I'm sure other frameworks provide ACL packages that you could use, or roll out your own if you have the time and understanding.
Good Luck.

Categories