CasbinJsGetPermissionForUser is too limited
See original GitHub issueHey everyone,
I’m checking out casbin because I’m considering to use it for a project. What especially caught my interest, is the new casbin.js because no other go authorization framework seems to provide anything similar. While I was playing around with it, I noticed limitations of CasbinJsGetPermissionForUser
, which I would like to discuss:
(I hope this is the right repository to discuss, otherwise feel free to move the issue around)
deny permissions
CasbinJsGetPermissionForUser(...)
cannot be used with any allow/deny models because the .eft
information is completely stripped, i.e. any deny
permission becomes an allow
permission.
Standard rbac_with_deny_model.conf and rbac_with_deny_policy.csv make CasbinJsGetPermissionForUser(e, "alice")
return
{"read":["data1","data2"],"write":["data2","data2"]}
Not only is data2
duplicated, but the second time it’s actually a deny
rule and here it shows up as a allow
rule.
Idea
This might be solvable by more or less directly serializing the permissions as they are returned from e.GetImplicitPermissionsForUser(user)
. Otherwise I’m afraid with whatever we come up, will miss information for other model configurations because of the generic nature of casbin.
This would probably mean that casbin.js would need to have access to the model definition to know how to interpret the permissions? If that wasn’t the case, we wouldn’t need the model configuration on the server side either …
role inheritance
CasbinJsGetPermissionForUser(...)
does not handle permissions for subroles.
Standard rbac_with_resource_roles_model.conf and rbac_with_resource_roles_policy.csv make CasbinJsGetPermissionForUser(e, "alice")
return
{"read":["data1"],"write":["data_group"]}
So e.Enforce("alice", "data2", "write")
will be true on the backend, but false on the frontend because because subroles are missing from the response and so unknown to the frontend.
Idea
For this very specific use case I added this to the loop:
subRoles, err := e.GetUsersForRole(role)
if err != nil {
continue
}
for j := 0; j < len(subRoles); j++ {
permission[action] = append(permission[action], subRoles[j])
}
and it works. But it only handles one level of subroles (does casbin on the server side handle nested resource role permission deeper than one level?) and it seems to be very specific to this use case.
To make this a bit more abstract: all roles of the user and the roles of resources that the user has permissions for should be known to the frontend.
Can this be done in a generic way at all and especially without leaking possibly sensitive information to the frontend?
Conclusion
CasbinJsGetPermissionForUser
(and the format it returns) is in my humble opinion too limited. The structure of the response should be adjusted to be more generic and casbin.js should be adjusted to reflect a new structure.
If possible the data returned should be extended with resource roles.
I think it’s rather easy to come up with a solution that works for a specific use case, but doing it in a generic way that’s “upstreamable” might be rather hard. I’d be happy to hear your thoughts what can be done with reasonable effort as someone who is new to the project and then I’d be happy to work on that and upstream it.
Best regards, Dominik
P.S.: I’m also in your Gitter channel and happy to answer questions or discuss there too
Issue Analytics
- State:
- Created 3 years ago
- Reactions:2
- Comments:13 (4 by maintainers)
Top GitHub Comments
In my mind, the priority of the policies can be determined at the backend in some sort of other forms like the orders (The more ahead, the higher priority)
I believe the roles are not necessary to the frontend. The frontend doesn’t need to know which group the current subject belongs to. All the policies passed to the frontend are dedicatedly filtered out according to the subject and are anonymized. For example, if
alice
belongs togroup1
, the backend side will select all the policies aboutalice
andgroup1
, and anonymize the subject part of the policy before passing them to the frontend. From the frontend perspective, it doesn’t have any info about the groups of the user.Actually only I are focusing on the development of Casbin.js currently, so I put all the codes at local temporarily. And the policy selection stratagies at the backend side are extremely naive with lots of bugs. Once I believe it’s okay I will publish it and leave a link here.
This is not the key. Why I trying to use protobuf is just simply wishing to serializing an abstract class object (w/ some metadata) and passing them in between the frontend and backend. Actually maybe JSON is enough. Most importantly, as you mentioned, how to reduce the computational complexity should be the key challenge.
Yep I agree with that. The obfuscation features are just an add-on feature for CasbinJS.
Glad to see your valuable comments!
Current implementation of
CasbinJsGetPermissionForUser
only support for conventional ACL and RBAC models. What we currently doing is rebuilding the design of CasbinJS and looking for a more generic solution is to let CasbinJS support all models, like RBAC w/ domains and complicated ABAC models.To minimize the the information passed to the frontend while maintaining any necessary features is not easy. For fully support for the features of Casbin, passing the model configuration and some required policies (related to a specified subject) will be a generic solution. Temporarily we are trying to anonymize the request subject and generate the minimum information that enough for the frontend enforcement.
It could be something as follows.
Imagine we are using an RBAC models, with the following model configuration and policies:
When a frontend querying the permission of
alice
, the backend Casbin.Js core will produce the minimum info:As you can see, only very few policies and matcher are used at the frontend. Frontend visitors have no idea about the backend access-control model. Meanwhile, with such permission, CasbinJs can do the enforcement at the frontend (with a lightweight enforcer similar implementation as the Casbin enforcer)
Such methodologies support for other models including rbac_with_not_deny.
This solution is still experimental. Currently I attempt introduing protobuf to help maintain, serialize and transmit the data.
The mentioned solution could still leak some sensitive information. For that I am considering some encryption methods like RSA.
Feel free to leave your comments!