I'm creating a Symfony2 website that has users and each user can have multiple permissions like this:
User1: manage users , manage sales , manage repository
User2: manage repository
user3: manage sales , manage repository
...
for such a system what is the correct permission system to use?
Roles or ACLs or voters or something else?
Thanks
Roles
Roles are OK if you want to grant "general" permissions.
For example, if you need user to be able to manage all or users, then you can create a role for it, for example ROLE_USER_MANAGER. Or if you want to grant him rights to manage sales, you can grant him ROLE_SALES_MANAGER role.
So basically, use Roles when you have limited number of permissions to some entities generally.
You can use them for other stuff by granting roles that contain entity names and ids for example, ROLE_MANAGER_REPOSITORY_23 and then using custom voters you can know that users with that role can manage repository with id 23. Even though this approach can work, I personally don't like it.
ACL
If you have a lot of dynamic permission granting, especially towards individual models, then ACL is the way to go. It is usually a bit less performant, as it needs to fetch more data from the data store, but is a lot more suitable for this purpose.
With Symfony2 ACL, it's incredibly easy to grant and check permissions, and even to allow individual users to grant permissions to each other.
Furthermore, introduction part of Symfony ACL docs shows you both of these approaches and also point out some ups/downs for each.
Related
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.
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.
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.
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?
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.