Since you asked for my personal opinion, then I would say Postgres Row Level Security for AuthZ. RLS is as powerful as it is flexible. It's fully-integrated with the rest of the Supabase stack, and it's portable if you don't like supabase - just pg_dump and take it to your favourite Postgres provider.
That said, I understand why it's useful to have something more structured like RBAC. We have experimented with a ideas here (specifically ABAC), using a custom libraries/extensions/custom claims[0]. We do something similar internally, but aren't 100% happy with the developer experience and don't plan to release it any time soon.
I'm sure the Auth team won't enjoy me saying this, but I like the idea of Zanzibar. I've seen some experimental Postgres extensions[1] that combine Oso[2] + RLS which I'd love to try when I get time.
[0] custom claims: https://dev.to/supabase/supabase-custom-claims-34l2
[2] Oso + RLS: https://github.com/MFAshby/rls_oso
[1] Oso: https://www.osohq.com/
The UX definitely isn't optimized for Supabase, but I'd love to learn more about how that could be improved. I suspect it might be complicated if Supabase assumes RLS for everything.
Glad to chat with anyone privately if they want more details.
Re: RLS:
Pros
- The simplicity+security is hard to beat
- Supabase is built around it. I really want the purity of just one platform.
Cons (in order)
- Our enterprise customers need regular oversight of policy + logs for their compliance (and our ongoing relationship). RLS doesn't expose that afaik.
- RLS can't control access to API end points in places like Edge Functions (again, afaik). Same for any 3rd party systems you might have mixed in.
- In my experience, RLS has quite a few foot guns in it as schemas migrate and evolve (security gaps open up, or recursion bites you).
Supabase Logs will be fully-integrated with the rest of the supabase stack. Since the Auth JWT flows through the HTTP Authorization header, into PostgREST, then into Postgres, we can pluck the Supabase User ID out of the JWT and store it alongside every log entry. You will be able to reference/join every authorized action in your database to an authenticated user.
> RLS can't control access to API end points in places like Edge Functions (again, afaik).
also correct, for now. We released the Edge Runtime[0] this week, and plan to use it as a scriptable Proxy.
> In my experience, RLS has quite a few foot guns in it as schemas migrate
A very fair point. We hope that we'll be able to provide some tooling here.
Thanks for all of this feedback - it's incredibly useful. Our team read the HN comments thoroughly and it shapes our ideas for the product going forward. We have some gaps to fill for your requirements, but we'll get there.
[0] Deno Edge Runtime: https://supabase.com/blog/edge-runtime-self-hosted-deno-func...
- My request with Supabase Logs is that they're easy to format in ways auditors expect (i.e. similar to major tools). That would be a headline benefit, because:
[1] As your customer, I have an easier time with SOC2
[2] In turn, I can pitch that to our enterprise customers: "your compliance will be easier, as your policy and log audits with us will match your other vendors"
I'm going to shoot this to your support channel, but a little more tiny feedback:
- There's no local way for a webhook Edge Function to flag "--no-verify-jwt", which means my local test environment can't be consistent with staging.
- I'm having to use Edge Functions for webhooks despite Postgres Functions being more desirable, because either Kong or PostgREST always requires a JWT. I'm guessing the switch to Deno will make this solvable.
If you use Supabase CLI to serve functions locally, you can use the `--no-verify-jwt` flag, ie. `supabase functions serve --no-verify-jwt` will skip JWT checks locally.
Is that what you're after? if you have any further issues with serving functions locally, can follow up on the support ticket.
What format(s) would you need?
And if this is Supabase hosted, you can reach out to support and we can do that for you.
Log drains is high on the list for the hosted platform too.
Additionally, I find it hard to keep a good overview over the rules. E.g., in a multi-tenant application one needs to secure every table with a restrictive rule, and it's easy to make a rule permissive, since that is the default & it's not indicated in the Studio UI.
When generating migrations with 'supabase db diff' views are being recreated without 'WITH (security_invoker)' even though they had security_invoker turned on before, leaving your database exposed. Easy to miss, even when you're aware of that.
RLS is just so full of footguns that I find it hard to justify using it in a production system.
(But otherwise I love Supabase! Great job.)
for this Launch Week we focused on generating policies (more on that in tomorrows launch week). This is hard for a lot of our audience who aren't familiar with SQL.
In the next few months we'll work on simulating a policy - being able to choose a specific user and see what data would be returned for that user.
We also have `supabase test db`, in case you missed it. It wraps pgTAP and pgProve so that you can write database tests.
> recreated without 'WITH (security_invoker)' even though they had security_invoker turned on before
we use migra for diff'ing. Thanks for raising this - we'll file a bug report asap.
* Permit.io: https://www.permit.io/
* Oso: https://www.osohq.com/
And Otterize has an interesting model if you are in the k8s ecosystem: https://otterize.com/
I don't have first hand experience with any of these folks, though I have chatted with some of them.
This is perhaps a future topic, but to me it extends out of SSO:
Paul (@kiwicopple), do you have an opinion on which enterprise-grade AuthZ provider works best with Supabase?
I suspect it's Cerbos or Casbin, but if you ever do it in house (and since you've nailed AuthN that makes great sense), my wishlist:
- It should be as simple as an API end point, .approve(auth.jwt(), Array<Role | Permission>). I.e. be available in Edge Functions, Postgres Functions, and anywhere else.
- Use a policy schema with the most industry support for easier acceptance/integration with the enterprise.
- Flesh out with enterprise-ready policy auditing tools, logging, etc. This is the real time saving for developers.
- I really recommend Tailscale's ideas for better RBAC in https://tailscale.com/blog/rbac-like-it-was-meant-to-be/