question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

CasbinJsGetPermissionForUser is too limited

See original GitHub issue

Hey 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:open
  • Created 3 years ago
  • Reactions:2
  • Comments:13 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
kingiwcommented, Sep 20, 2020

how is the frontend supposed to prioritize conflicting rules?

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 think it’s necessary to make all roles related to the user (obviously other users and their roles can be stripped) available to the frontend - or at least make the frontend support it.

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 to group1, the backend side will select all the policies about alice and group1, 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.

Is there any branch to look at?

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.

Does protobuf really help so much with the size and is that really such a big issue?

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.

You could call it obfuscation at best IMHO.

Yep I agree with that. The obfuscation features are just an add-on feature for CasbinJS.

1reaction
kingiwcommented, Sep 18, 2020

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:

# Model configuration
request_definition, policy_definition, policy_effect...
# Matcher Definition
m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act

# policy
g, bob, group1
g, alice, group1
g, group1, group2,
p, group2, write, data
... other policies not related to alice

When a frontend querying the permission of alice, the backend Casbin.Js core will produce the minimum info:

# Model Configuration
request_definition, policy_definition, policy_effect...
# Matcher Definition
m = r.obj == p.obj && r.act == p.act  # g(r.sub, p.sub) is removed because the condition can be determined at the backend.

# policy
p, _, write, data # subject is anonimized

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!

Read more comments on GitHub >

github_iconTop Results From Across the Web

No results found

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found