Open thorwebdev opened 8 months ago
@thorwebdev thanks for bringing this up. After some review, I'm not sure this would improve this package much. It may actually be worse in a couple ways. I have answered a question about this on reddit if you are interested in learning more.
EDIT: adding it here so that it is preserved regardless of what happens on reddit
Question asked by a reddit user:
Very cool project! We have also been looking for a better RBAC solution for our Supabase app but haven't settled on one yet. I'd be curious to hear what you think of the approach mentioned in the official docs (https://supabase.com/docs/guides/database/postgres/custom-claims-and-role-based-access-control-rbac)?
Did you ever think about also incorporating role_permissions into your project?
My response:
I've actually been keeping on eye on those docs for a while. Currently, their auth hook approach is very similar to the way this package used to work. By storing the claims in the jwt, you make them accessible both server side and client side without requiring additional queries just to fetch them per request. This is great for performance. Unfortunately, it also means that if the claims change after a JWT has been issued, they won't take effect until the active JWT with the old claims expires and gets renewed. This means that if you are trying to revoke someone's access, you can't do it instantly. If you are trying to grant additional permission, the user won't be able to use it until they log out and log back in or until the JWT expires.
My library takes the approach of caching the claims in the user's raw_app_meta_data each time the claims are updated. This field is included in the JWT so it provides the same functionality as the official docs (albeit with a slightly different data structure). The difference comes in when a query is performed. My library uses the postgrest db_pre_request hook to trigger on all incoming api calls to postgrest, fetch the current state of the claims cache (not the JWT), and inject it into the request context. My RLS policy convenience functions check this request context first, before falling back to the JWT method. This means that as long as you are making queries via postgrest / supabase sdk, you are more secure than the official approach since it will always use the most up-to-date claims. There is a minimal performance impact to this approach because it fetches the claim cache for each request (but not for each row). I have found this impact to be negligible and definitely worth the added security for my application.
Finally, the official docs guide you on implementing RBAC, but not Multi-Tenant RBAC. This means that while you can assign roles and permissions, it isn't obvious how to have multiple teams/organizations of users that each manage their own roles/permissions within their team/org. My library supports this natively by using groups to organize collections of users and then any number of roles per user, per group. You can use the same dot notation from the official docs to add permissions to this as well.
In summary, my package should accomplish everything the official solution does while also adding security, more convenient methods to call in RLS policies, and multi-tenant support, if you want it. Let me know if I can help clarify any of this futher. Thanks for checking it out, I appreciate the questions and the feedback!
@point-source I am thinking of going with your implementation. How hard is it going to be for me to migrate your implementation to auth hook, if I were to migrate for x or y reason?
Hey there, thanks so much for this awesome project!
We've released some official guidance around custom claims & RBAC using the new Auth Hooks approach: https://supabase.com/docs/guides/auth/custom-claims-and-role-based-access-control-rbac
Would love if you could review and see if that would make sense to adopt for this project?
Thanks 💚