This is more like a question for an advice rather than a precise answer...
In my CakePHP app, I will have backend users and frontend members. They have completely different roles and permissions (users are application managers, members are visitors that register on the website without any access to the application backend). Should I use different tables for these two authorization types, or should I just manage them with a role parameter and bind tables to their profiles depending on it, and why is one solution better than the other?
Use the same table and role or type field. You will have only one login and it will be easy to manage the accounts.
Use ACL or a custom permission system to allow them to different controllers/actions.
For permissions, I have 3 ways to do it :
The strict-role way :
Every role of your application has access to functions with their prefix, but not any other prefix.
Ex : admin has access to admin_edit, but not customer_edit
You add a role varchar or enum in your users table, the routing prefixes in Config/core.php and you allow the access in a AppController::beforeFilter : each role is allowed to access to his prefix only.
The hierarchical way:
Your application's roles are ordered in a hierarchical way, where a role has access to his prefix and every prefixes under him.
Ex : admin has access to admin_edit and customer_edit, but
customer has not access to admin_edit
You add a role varchar or enum in your users table, the routing prefixes in Config/core.php and you allow the access in a AppController::beforeFilter by checking for each $this->request->params['prefix'] which roles can has access to it.
The custom way:
You need your admin to access to some functions, but not all. You need another role to access some functions admin can access, and some functions admin cannot.
Ex : admin can access to admin_edit and customer_edit, but not
customer_create or user_stat. customer can have access to
customer_edit, customer_create and user_stat, but not admin_edit or
user_edit
Use ACL. It's not the easiest way to manage permissions into your application, but if you want specific permissions, it's the best way. So remember this : only use ACL if you really need it.
I agree with cornelb: one table only. Here are some additional reasons:
If you add foreign key constraints, it might be messy to make them refer to both the app managers table, and the visitors table. Always when you want to point to a user, you'd need 2 fields, instead of 1 (a field pointing to the managers table, and one to the visitors table — and exactly one of them has to be null). And what if you need 2 user id fields in a row, with foreign keys? Then you'd suddenly need 4 fields. Simper with all keys pointing to just one table (and user type decided by the above-mentioned field).
Sometimes you might want the user id be part of a primary key — but that's more complicated, if you have two different user id fields, one in each table. Because then the database cannot guarantee that each user id is unique — you'd have to do it yourself at the application level.
Related
I'm currently working on a project where a user can have many roles, and each role has assigned one or many permissions. Permissions describe the actions that a user can apply to ressources. For example let's consider that I have three ressources that I can interact with using my API : users, books, payments.
I'd like to have all users able to update their personal informations like phone number... etc. This led me to give update permission on user's ressource for all users. But the problem is that I want them to be able to updates their own profiles only. Furthermore, some users have admin permissions and can change other users permissions, therefor they have another kind of update permission on user's resource.
So my question is : what's the best way to design the permission table. Below you can find my schema design. Thank you for your answers in advance.
User(firstName string, lastName string, roles Role[])
Role(name string, description string, permissions Permission[])
Permission(name string, effect 'Allow' | 'Deny', resource string, action string)
Well I am not entirely sure what you meant by resource and action. If you meant URI template and HTTP method, then ok. Otherwise you might need a different solution or somehow add parameters to your design if you want to allow or deny individual resources per id.
If we are talking about a REST API, which I assume, then you can do something like PATCH /api/v1/current-user/profile {...} for updating your profile and PATCH /api/v1/users/{user-id}/profile {...} to update somebody else's profile. If you meant controller classes and their methods, then you can do the same with two different controllers, something like CurrentUser.partialUpdate(params) and User.partialUpdate(params).
As of updating user permissions, I wonder how to do it, because you can update only role permissions and give or take away roles for the users in your model.
Another thing I don't understand that why do you need the allow|deny flags. If roles collide because users can have multiple roles or permissions collide, because you can both allow and deny the same thing, then how do you resolve it without a hierarchy? And if you don't have a hierarchy, then this flag is completely useless and just deny all and allow what is added to the role.
As of the one user multiple roles approach it is not a great idea, at least in places where people take security seriously a single account or at least a single session can have only a single role. Since this would make a lot of repetition I would solve this on a role level and make composite roles or support role inheritance. So for example the Administrator role would be the composite of the OwnProfileEditor and ProfileEditor sub-roles, which I would rather call Features or Capabilities or PermissionGroups rather than Roles.
Usually RBAC is not that flexible, so people tend to add per User Permissions to override Role Permissions. I would not do it, because you will end up with a mess if you follow that approach.
I am using AWS cognito for user authentication in the application that I designed. And where ever there is a need for user audit in the application, I have used the id from cognito as if it is a foreign key from another table(I am using a relational DB).
Even though this works, this approach somehow feels improper. Is there any other proper way to design this?
In my application, the user logs in with his email address (common scenario). Hence, by construction the email address is a unique identifier both in cognito and in my database.
My database creates a user id for each new user, and that is the main identifier I use in my app (note that this identifier has nothing to do with cognito).
Cognito also assigns an id to each user (which it calls "username"), but I never reference that id (nor have I ever felt the need to reference it). I have been in production for several years, and I have never regretted this decision.
Upside of not linking user ids:
full flexibility (e.g. I can decide that I want to create a new user Object in my database for a particular cognito user. I can keep the previous user e.g. as a backup, even though it is not linked to the cognito user).
less work: i don't need to make sure the ids in my system are in line with those in cognito.
Downside of not linking user ids:
maybe it's faster to query cognito using the username field than the email field? maybe that could be an advantage for some use cases?
I really need to get some database design help. I have a platform where we have a table called users. It has a column called role for defining whether its a customer, provider, manager. But column email is unique. So at first we thought that its okay clients will make new emails. But then later it was not formidable. They wanted to use same email for both platform (Just like google single email for everything) So I want to really know the very basic idea of how Google maintains it. What should be the very basic db schema for it?
It looks like you need to break out roles from the user table.
If you are able to go this route;
user table - email as the primary key
platform table - platform id/name as the primary key
user/platform table - combination of email/platform id as the primary key
This will give you the ability to store and query when users have multiple platforms and/or roles.
Is it possible to use SQL's Dynamic data masking with Entity framework?
If it is possible, is there any way to combine it with Asp.Identity?
Project I'm working on requires that data is masked for certain user roles and visible to others.
We are using database first approach and Entity framework with data fields masked with:
MASKED WITH (FUNCTION = 'default()')
that need to be visible to admins and remain masked to other user roles. User roles are defined thru Asp.identity.
If it suits well your app architecture you can try approach from this blog post this blog post.
In two words you can create special db user which will represent your "other user roles". And then create two instances of DbContext: one for admin and one for the rest of your roles. So, basically, it's all about user identity provided in connection string.
Correct instance of DbContext with right connection string based on current user you can, for example, provide with dependency injection.
Is it possible to use sharing rules for users WITH profiles. Is there any use of them if users have profiles? Or does the profile completely override record access so that i can forget about sharing rules?
I'm in situation where ALL my users have profiles. What I wanted to do was to GRANT "Edit" access for certain records to certain user groups. Is that possible?
Thanks!
A user's role dictates which records they can SEE, while their profile dictates what they can DO with those records. Typically the only case where the profile overrides the role is if their assigned profile contains one of the "View All" or "Modify All" permissions on an object.
For example, if you have a role hierarchy set up that divides different branches of your organization, it may be useful to hide the data between these branches. In this case, you would want to set the org-wide default to Read Only, and provide sharing rules that grant access on an as-needed basis (these sharing rules would be based on a user's role, public groups, or queues that they belong to).
Sharing rules also allow you to specify whether you want to grant the ability to edit records or simply view them. So in your case, you will want to create a sharing rule granting edit access on records owned by one group of users to your second group of users.
See the Overview of Sharing Settings for more information.