How to structure user permissions for a cms - php

I am creating a custom photography CMS system and need to implement a user authentication and permissions system. What are the usual practices in the industry to go about creating such schema.
Basically I need to have users, and users can be of different type. Some users lets say can only create galleries, others can only edit them, or edit only certain galleries, etc. So how should this be structured. I am using MySQL database and I am using PHP to code the CMS.
I tried looking on Google however only found articles which explain how to create users for the actual MySQL database. I will appreciate a link to an article which explains how this sort of stuff should be done.
Thank you in advance.

There are two common approaches to this problem, both involve breaking apart the allowable operations into something discrete that you can name. (Delete posts, create galleries, upgrade the code, dump the database, launch the missiles, open the garage door.) Give each one of these a bitmap in a bitvector (if you intend on having fewer than 32 permissions, this is a nice and compact storage mechanism; if you think it'll grow beyond 32 permissions, the size of a typical integer, then maybe a table in your database..)
So, you can either map users to permissions directly ("I want to grant gallery_create to sarnold") or you can map users and permissions via classes of users ("I want to grant gallery_create to all members of the art_curator class; then I wish to promote user sarnold from docent to art_curator").
If you map users to permissions directly, you may find a hodge-podge of strange permissions in deployment years later. If you map users to classes, you may find yourself with artificial classes of users because you trusted one specific person with a privilege, but not other privileges.
Figuring out the best way to address this mapping is still an open problem; I have written about different types of permission models Modelling a permissions system that may be too much or may be too little information, depending upon how complicated you would like your system to become.
If you would like to just store permissions in bitmaps (e.g., the Linux kernel's implementation of CAPABLE() for CAP_SYS_ADMIN, CAP_DAC_OVERRIDE, and so forth) then you could add new privileges with something very simple:
if (requested_new_permission == "CAP_SYS_ADMIN")
user->permissions |= CAP_SYS_ADMIN;
else if (requested_new_permissions == "CAP_DAC_OVERRIDE")
user->permissions |= CAP_DAC_OVERRIDE;
...
Then when you need to test the capabilities:
if (CAPABLE(user, CAP_SYS_ADMIN))
reboot_server();
and the macro CAPABLE() can look like:
#define CAPABLE(user,cap) ((user)->permissions & (cap))
(Forgive the C, I just don't know php very well; I've been forced to fix far too many php bugs to want to learn it myself.)
If you want to map users to permissions through user classes, then it might be three tables: a users table, a groups or classes table, and a permissions table. classes has columns for user_id and permission_id. When you need to check if a permission can be granted, select the user's class, then select the permission in the class. (It's also been years since I've hand-written SQL; I'm sure a single query can give you a yes or no answer, but I'm not sure if it would be a multiple table join or using subqueries or if it would just be easier to make two queries to the database. :)
Hope this helps.

Related

How to properly extend a database model with PHP

I know that the title of this question is not intuitive, but let's go to the question.
I've designed a "core system" for all my backend web apps (control panels, systems to manage clientes, balances, etc). This "core" is the start point for developing new modules according to the new system specific needs, but I always keep the "core modules":
Users (to manage user roles)
User type (in distinct systems there are distinct kinds of users, so it's nice to manage them dinamicly)
Modules (to create new modules and add permissions to them)
Dashboard
My main question is for the User module. Since it has the default columns
UserId; Name; Login; e-Mail; Password; isRoot; isPowerUser; UserTypeId
I want to create new control panels and apps, but dont want to change this table to keep the "core" updatable with an easy process in the future. My ideia of design is to create table named User_Extra which will contai all the extra columns for this specific user.
Is this a good approach? I'll also will create a new class named UserExtra.class.php.
If u want to take a look at the project to get the ideia: https://bitbucket.org/alexandrekop/akop-core
Imagine looking at your database schema, and seeing a table named "user_extra" with a bunch of fields that aren't related to each other in any way and each field is related to a different module, does it feel 'right'?
My suggestion is to split the extra fields into relevant tables, possibly per module, or per logical group.
For example, if one module was related to addresses, you would have a table "user_addresses", with things only specific to the address of the user.

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.

Build a Better Access Control System

I'm in the process of a building an access control system as part of a web framework I am developing. I want to make it super flexible and awesome. Can you help me by providing input and insight on my design? Here is my work so far (my specific questions are at the bottom):
Users
Users have a username (32 characters, no spaces) and password
Users have one or more e-mail addresses that must be verified
Users may login using either their username or any of their e-mail addresses
Users may be associated to zero or many accounts
Accounts
Accounts represent one or more users
Each user may have specific permissions or roles for an account (e.g., account owner or "can add new user")
All accounts are tied to an account type
Account Types
Account types have zero or many account type roles
Account types have zero or many account type features
Account Type Roles
E.g., "Owner", "Administrator", "Power User", "Guest", etc.
Account type roles are a collection of account type permissions
Account Type Permissions
Account type permissions are specific actions in the system that application logic will verify against
They may reference a parent, so they can be hierarchically grouped
E.g.:
"User Management"
"Add User"
"Remove User"
These permissions may be specifically for an account type feature
Account Type Features
Account type features may be activated on an account to give it more permissions
E.g., "Standard Account" or "Premium Account"
These features, if activated on an account, will give the account owner greater access to the system
They are tracked when they are activated or deactivated and can be billed against periodically or on demand
Questions
What is the best way to have application logic check against a user action? I was thinking of storing all of a user's permissions in an object for their session (which would require a logout/login to refresh permissions, which I am not a fan of - any ideas on real time permission management?):
{
"All Permissions": {
"User Management": {
"Add User",
"Delete User"
},
"Premium Account": {
"Download Files",
"Upload Files"
},
}
}
I would then declare permissions that are required for a specific action in the system. Maybe something like:
Permission::require('Add User');
If the declared permissions were not in the users permission object, the request would fail. This seems kind of intense for each user action though. Also, what if another subset of permissions has the string "Add User"?
Thanks in advance for any help with this!
Looking at your Account Type Permissions, it appears you have an Access Control List (ACL) style system design in mind.
If you want to make it super flexible and awesome, then I'd suggest this is not a good design. ACL system's work for simple permissions - and maybe that actually is ok in your scenario - but as soon as the rules for granting permission become even the slightest bit dynamic - that is, relying on any contextual data beyond the user's identity or roles - ACL's fall flat fast.
This video goes into some detail about the failings of ACL's and discusses alternate ways to implement access control that accounts for real-world situations.
Also, this has been done before (though there's surprisingly little out there for implementations we can look at); perhaps have a look at Rhino Security. Original link http://ayende.com/Blog/category/548.aspx is broken, so keeping internet archive link for reference.
One way I've seen that I like is a sort of "cascading" permissions. You have a core set of permissions - let's say read, write, delete - and those can be assigned to a group or a user.
READ USER1
READ USER2
WRITE USER2
READ USER3
WRITE USER3
DELETE USER3
Alternatively you can specify a "group" instead of a username.
READ SUBSCRIBER
READ EDITOR
READ ADMIN
WRITE EDITOR
WRITE ADMIN
DELETE ADMIN
USER1 SUBSCRIBER
USER2 EDITOR
USER3 ADMIN
And then you can simply use the values in the table to sort and look for records. This allows for the flexibility of being a member of multiple groups with mutually exclusive permissions, etc.
I would take a look at the Java system for permissions:
http://download.oracle.com/javase/6/docs/api/java/security/Permission.html
It uses "implication logic"; that is, the permission object is what decides whether the given action is allowed (i.e. whether the permissions "implies" access to a resource). I would also check out the BasicPermission as it has a pretty straight-forward namespace spec for permissions. In your example it would be (following the CRUD nomenclature)
user.create
user.delete
file.read
file.create
In our webapp, we assign a permission to each resource or procedure that can be requested, and a set of permissions to each user. We then do a
boolean isAuthorized = user.permissions.implies(requestedResource.permission); (standard encapsulation implied)
to determine if the user is allowed access.
Here is my two sense, for what it worth.
First I would say, when you start the design of this, think of OOP and how it would apply to entities within the system. Users, User_Role, Roles, Role_Permissions, Accounts, Account_Types, Account_Type_Features, etc.
USERS:
- Should be allowed to use OpenID as it is gaining traction
- The option to select between an ID or UUID for database portability
USER ROLES: (not ACCOUNT TYPE ROLES) I would encourage you to be very specific here. For example, where do you draw the line between power user and administrator?
What's the difference between ADMIN and OWNER? As long as these are clearly defined (and not blurry), then it will work.
If there is any question amongst your user base, pretty soon you will have a convoluted set of roles and permissions.
I would keep this to a minimum to keep things clean. Users will figure out how to work with what they are given.
In addition, I would change this to USER TYPE ROLES. The roles should apply to the user, not the account.
ROLE PERMISSIONS: (not ACCOUNT TYPE PERMISSIONS)
This should be changed to ROLE PERMISSIONS. The permissions are extended to a users role, not an account or a user.
In my experience the more clear the design, the less room for confusion down the road.
Also, avoid ACL like the plague. Make it a simple one-to-one relationship. I have yet to find a reason to implement ACL
for any web based system. Other permission based systems are much easier to understand, maintain, and use. There is no sense
in complicating the matter.
ACCOUNT TYPE FEATURES:
Be careful not to obscure the Account Type Permissions and Account Type Features. Your first bullet point uses the word permissions.
Change it to features. The account type will activate more advanced / premium features (not permissions).
Permission Management:
For a stateless application running on the web, sessions are the way to go. The advantage is no roundtrips to the DB to constantly
check if a user is authorized.
Permission::require() should follow the same parameter definitions as the Sessions though. This will prevent overlap of other subset of permissions.
So the call would be something like Permission::require('User Management', 'Add User');
This means it would look for $_SESSION['All Permissions']['User Management']['Add User']
This will prevent ambiguity.
Remember SIMPLE is BETTER.
Zed Shaw had some interesting things to say about ACL's and their limitations. Definitely worth watching before you go any further down this route.
http://vimeo.com/2723800
I advise you to look into the Zend_Acl from Zend Framework. Like most Zend packages it has a steep learning curve. But when you fully grasp the resource, action, role relationship it becomes a verry versatile and powerfull foundation for your own ACL implementations.
Do some research into existing ACL packages and patterns.
I don't have any specific advice but two systems I'm familiar with that have very good flexible access/permission systems are Drupal and Plone. You could do far worse than copying how either of them work. They've had years of real-world testing behind them.
The semantics you are using are a bit confusing. For example Account Types of "Owner", "Administrator", "Power User", "Guest" seem more like "User Types".
Also, perhaps you could make the things you are calling "AccountPermissions" be a subclass of Account. This way depending on the type of the account, different permissions will apply.
Have a look here
http://www.sqlrecipes.com/database_design/fine_grained_role_based_access_control_rbac_system-3/
The concepts are basically the same and its nice to use and considerably fast for really fine grained access control.

Access control for multiple users in a web application

I'am working on a PHP + MySQL Social Networking application, now i need to setup different access control (read,create,edit,delete) for global (all items) and/or self items (item which created by themselves) for each module to group or specific user.
Does anyone has suggestions in doing this (table structures, etc)?
okay here i provide more detail, currently i have a tbl_module, tbl_user, and tbl_user_role. Each user and role can have different access to specific module.
read
update
create
delete
and devided by global access or self only (own account or records created by themselves).
and my current approach: i create another table to hold the access detail:
acl_uid
mod_id (fk module uid)
target_id (fk user uid or role uid)
acl_type (user/role to identify the target id reference)
acl_read
acl_update
acl_create
acl_delete
acl_read, acl_update, acl_create, acl_delete value ranges:
0 deny
1 allow
2 refer to lower priority check (if user has value 2 then refer to role)
3 self only
i believe that theres more efficient way to solve this, or may an improvement to my current approach.
thanks for your responses.
That's a pretty broad question, so you're likely to only get very broad answers.
Most CMS systems have a table that lists the types of content that can be produced on the system.
Another table describes how each type of content is displayed (on the front page, on individual blog pages, etc).
Another table gives each user one or more "user types" or "groups" such as admin, unregistered, moderator, etc.
A last table is an access table of sorts - it shows what each group has power to do, including the types of content it can create, edit, publish, etc.
I recommend you spend a little time studying the database schemas of other CMS software, such as Slashcode, Drupal, or one of the other millions of CMS systems.
-Adam
It is in fact a very broad question. Assuming you have a clear separation of application tiers (eg, using MVC), then this is the sort of stuff going in the business layer.
Taking your direct requirements, it could be fairly simple. In your users table, have a hasEdit, hasView, etc. For each item, attach a userid to it representing the creator. In the business layer, the rule is they have edit permission if they are the creator, or they have hasEdit = true.
Taking it up a notch, if you have different types, and the hasEdit permission is per-type, you need another entity for that.
userPermission
userPermissionId
userId (FK)
typeId (FK)
hasEdit (boolean)
hasView
etc..
To find out if they have permission to edit, you check if either they're the owner, or look up that items type and the current user in the userPermission table, and check hasEdit. You could make additional rules, like putting a global hasEdit in the user table. Or representing global hasEdit by an entry in userPermissionId with a NULL typeId.
This can get way more complex, using roles and variable numbers of permissions.. it all comes down to your requirements. You need to carefully spec out your business requirements (come up with a bunch of use cases), and then you can design from there. As is, there's really not enough information to come up with anymore than I've outlined here (and even this is probably not exactly what you need).
I like to use a kind of firewall rules approach or similarly a mysql tables rules approach: you can grant users or groups of users certain rights on certain objects or groups of objects. Make each rule be a row in your rules table. When you need to do an action like edit, you can inner join on your rules table for the current user, current user's group, the boolean edit column and the object id or object group. If you get any rows back then the permission is granted.
There are quite a few ways of designing security, and I've liked quite a few for different situations. There's UNIX-style user-group-other. I happen to like PmWiki's security model.
I developed a website which used user-role-permissions structure similar to Apache. With that website, I used a template system that used a header include file and a footer include file to wrap the page contents with the "standard stuff". A page with restricted content could set a variable to the required permission, that the header script looks for, and if set, calls an auth function that checks the user belongs to a role that permission.
The nice thing about using the user-role-permissions model is if most of your users fall into neat categories of authorization, setting the authorization for a user is a simple matter of adding the right role to that user. The permissions are linked to roles, not users directly, so you can adjust the permissions of entire classes of users easily.

Categories