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.
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.
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.
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 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.
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?