Anyone created a RBAC and ACL system? Comments on this design?

I'm trying to determine the best approach for a RBAC and ACL system. I want to store the roles and ACLs in the DB for easy updating in the future, so I don't think I can use the Roles and Permissions feature in the Security Provider. The Security Provider will stay a simple "is the user logged in" enforcer.

At the moment I'm thinking I'll need to add DB queries at the beginning of my API's Request Methods to check if the user has the appropriate rights before running any of the steps.

image

In addition to the tables that will store the data (tasks, contacts, etc.), I have created the following tables for the RBAC/ACL system.

  1. Account Table : Represents different accounts or organizations within the system.
  • Contains: Account IDs, account names, and other relevant details.
  1. User Table : Stores information about users.
  • Contains: User IDs, names, account IDs they belong to, and a reference to roles.
  • Relationship: Each user is associated with one account (foreign key to the Account table).
  • Relationship: Each user is associated with one to many roles.
  1. Role Table : Contains different roles that can be assigned to users.
  • Contains: Role IDs, role names (like Admin, Editor, User), and descriptions.
  • Relationship: Each role is associated with one to many permissions.
  1. Permission Table : Defines various permissions or actions that can be performed.
  • Contains: Permission IDs, names (like 'read', 'write'), and descriptions.
  1. ACL Table : Defines specific access control rules.
  • Contains: ACL entries that link users or roles to specific resources, specifying what access (defined in Permission Table) they have to those resources.

In this structure, users are linked to accounts and roles, roles are linked to permissions, and the ACL table provides specific access rules, tying users (or their roles) to particular resources (i.e. tasks, contacts, etc.) with defined permissions. This setup should allow for both broad, role-based permission assignment and more specific, user-resource-level permissions via the ACL.

For example, I have a task table. All tasks are related to an account. Each user is also related to an account, so they should only interact with tasks related to their account. Each user would also have a role(s) that give(s) them permissions (e.g. can delete, can edit) related to the task module.

The permissions would be tied to the Request Methods in my API. So within the request method to delete condition, I would have a database query that checks if the user is the creator of the record, if they are not, then the next check would be to see if they had a role/permission that allows them to delete.

Further, let's say I wanted to share this task with someone that is not a part of the account, this is where I would create a record in the ACL table specifying the user_id, the task_id, and read access through a "Share" action and I would also build the checks into the GET method that would happen after the check for creator and user role/permission.

Any thoughts on anything I may be missing or a better design?

1 Like

Only one thought comes to mind… store all your security actions/conditions in a library and just include the library on every api.

1 Like

Thanks Ken. I’ll look into using the library. Admittedly, I’m not using the library right now and I’m not quite sure what I could use across all of the APIs.

In a project I attempted to implement ACL (or something similar) with Library actions, but it’s too messed up to serve as an example. Think of it like 3 different ways I tried to do, so everything is just mangled :upside_down_face:

Posting screenshot of one of the attempts:


Unfortunately, I don’t have a screenshot for the Exec step that calls those checks, sounds I attempted to do another method instead, which I’m not going to post to avoid creating further confusion.

For all approaches, I took inspiration from here:

2 Likes

Here’s the rest of the design.

I created a library action user_role_check that gets placed in all apis.

Here’s the query

Here’s my Contacts api.

  1. It first gets the user’s role and related permissions, then a sequence of conditions are used to route the api to the requested action.

  2. I added conditions to check for the specific permission that would give the user the ability to perform the action (e.g. contact_update or contact_create)

Here’s the Permission table. It defines the actions a user could take.

Here’s the Role table

Here’s the Role_Permission relationship table relating permissions to roles

This allows me to easily setup new roles and permissions and then use them to enforce abilities within APIs or to enforce what is shown in the UI by using conditionals or show/hide attributes based on the role or, more granularly, the permission.

6 Likes