Reputation: 2554
I'm designing authorization service. It performs access control based on roles assigned to user and permissions set on content. User can belong to multiple groups. These groups can belong to other groups too. The depth of group under a group under a group is not that large. Content can be shared at user level, or group level. Content can be shared with multiple groups too. Operations allowed on content are to-read
or to-read-write
.
Here are my thoughts on designing solution to above problem. The thing is, it looks very simple. I'm concerned I'm missing some point which will hurt in performance or scalability of the design. Here is the design.
Data store:
Each User can have multiple roles. A role is a string and looks like namespace. supergroup.group.subgroup.rolename
.
Each Content can have multiple permissions. A permission is a string and look like namespace with operation type prefixed. canreadwrite.supergroup.group.subgroup.rolename
Authorization algorithm The authorization function algorithm looks like this (PS this is just to show basics, in practice roles and permission arrays will be sorted and some form of binary search will be used to do this matching)
public bool CanReadWrite(string[] roles, string[] permissions)
{
foreach (var role in roles)
{
foreach (var permission in permissions.Where(s => s.StartsWith(canreadwrite)))
{
string barePermission = permission.Remove(0, canreadwrite.Length);
if (role.StartsWith(barePermission))
{
return true;
}
}
}
return false;
}
Do you see any issue with this design? Any performance issue? Scalability issues?
Upvotes: 2
Views: 434
Reputation: 7210
I can't find any real issue with the approach except for two quite weird top level groups called canreadwrite
or canread
. If a dumb amministrator creates such group, your algoritm would fail.
Thus I suggest to use something like canreadwrite:supergroup.group.subgroup.rolename
.
As an alternative you could format association like rolehierarcy:permission, testing the role with StartsWith(roleName)
and the permission with EndsWith(":" + permissionName)
.
Eg supergroup.group.subgroup.rolename:canreadwrite
Upvotes: 0
Reputation: 1130
Your application is not very clear, especially how these hierarchies of user groups relate to the roles/permissions design.
First I'd avoid to implement binary search by your own, but just to use dictionaries.
Second I'd assume you might have large numbers of content items and large numbers of users. It looks like you could end up with large numbers of "dotted permission strings" per content item, but you should keep the number of role/permission entries per content small for performance and maintainability of rights.
Maybe you can split the role definition/maintenance from these user group hierarchies, i.e. content items do only "know" some roles, not these groups.
Third, if you really need hierarchies of user groups, I'd consider to allow to attach roles/permissions on higher level groups where approriate to avoid the need to define/maintain roles/permissions always on lowest level (assuming many low level groups possible).
s.a. RBAC at wikipedia
Upvotes: 2