Hello, I've been using Supabase since it launched and really like the RLS solution for it.
Even implemented per user role system before Supabase introduced Custom Claims & RBAC.
Now that my projects have grown, I need to migrate some parts of the code to microservices and move them to something like AWS lambda (they run for 30-60 seconds and use 2gb memory, so edge functions are a bit expensive or straight up cant handle that)
I wanted to introduce RLS access for each microservice that I need.
Lets say image generation service, it needs access to Supabases file bucket and some table, so generally speaking the microservice should be able to do only 2 things on Supabase and nothing else. That way if microservice is compromised, leaked keys couldnt do much damage.
So I went around and couldn't find any solutions for this, but i tried:
Works out of the box, can create a key for each service, revoke key if required.
But has elevated access and if compromised, back to mcdonalds.
When creating a JWT key for Supabase signing, you can add your own private key, that way you can sign keys from local machine with roles without requiring an user, so a generated JWT key with private key, could be read and used with RLS.
But you can only have 1 active signing JWT key (if you dont count standby or previously used keys, but i dont think using previously signed keys as access managment is a good solution), meaning if 1 service is compromised, JWT singing key needs to be rotated and new JWT keys have to be generated on every microservice.
Since Supabase already has Custom Claims & RBAC, I could technically generate a user with specific role, then save credentials as environment variables for microservice and microservice could authorize that user before each run. If compromised, i could simply ban the user.
But that would be an extra request on a microservice, in the long run it would accumulate spending.
TLDR, is there a way to do server to server communication (microservice -> supabase), where authentication flow can be done via API key that is not with elevated access and the key can be scoped with a role for RLS?.
The user is seeking a way to implement role-based API keys for microservices in Supabase to ensure secure server-to-server communication. They want to limit access to specific resources to minimize damage if a key is compromised. They have explored several options, such as service role API keys, signing their own JWTs, and using service user accounts, but each has drawbacks. They are requesting a solution that allows scoped API keys with role-based access.
this is a really well thought out breakdown of the options. the service user accounts approach is honestly the most practical one ive seen people use for this. the extra auth request per run sounds annoying but if your functions are already running 30-60 seconds an extra 50ms auth call is nothing in the grand scheme.
one thing that makes the service user approach cleaner is to generate the session token once on cold start and reuse it across invocations until it expires. lambda keeps containers warm for a while so you wont be re-authing every single run. just cache the token in memory and refresh it when the jwt expires. that way your cost stays flat.
the signed jwt approach is what i ended up doing for a similar setup. the single signing key limitation is annoying but you can scope the jwt claims per service by giving each one a different custom role in the payload. so service A gets a jwt with role image_generator and service B gets role data_processor, and your RLS policies check the role claim. if one service gets compromised you revoke its specific jwt without rotating the signing key itself — just add the compromised tokens kid or jti to a deny list.
honestly supabase is missing a first class solution here. scoped api keys with per-key RLS roles would solve this cleanly but i dont think its on their roadmap anytime soon
I didn't know you can actually revoke a jwt key only signing keys, how do you do that :D