Policy for ADMIN/SUPER_ADMIN access returning empty results
Hi everyone,
I’m trying to create an RLS policy that only allows ADMIN and SUPER_ADMIN users (based on their app_metadata.role in the JWT) to view rows in my user_roles table.
Here’s what I currently have:
alter policy "Admins can view user_roles"
on "public"."user_roles"
for select
to authenticated
using (
((auth.jwt() -> 'app_metadata'::text) ->> 'role'::text) = ANY (ARRAY['ADMIN'::text, 'SUPER_ADMIN'::text])
);
The role field is definitely inside app_metadata in the JWT, but when I test this, even admin users get back an empty result set.
Am i missing something?
10 Replies
Can you show an example of your app_metadata?
Try just comparing to a single value.
Also if using next.js and changing RLS behind the scenes caching may not reflect the changes if you ran the operation before.
I have this user who currently has the admin role.

Also try it from the sql editor with impersonation
Okay. I'll try that.
For added context, I'm using the following functions in my code
could it be an issue with the type of auth keys i'm using?
Have you been able to resolve this @Gabriel Damian ?
Not yet. I'm thinking its an issue with the headers I'm using (anon key). I'm refraining from using the service role key because I believe it should work with the anon key. I'm just not sure
Did you try the SQL editor to rule out your app?
Simplify the RLS to just TO authenticated and True to see if you can access it at all.
Check the API Gateway log for the call and you can see the user info making the call including the role (should be authenticated).
Anon key is what you want to use for the apikey otherwise you have to be serverside only to use service_role to bypass all RLS.
Yeah I think it's because above in the pasted text, it's set to anon , I mean the getSupabaeHeaders function headers
However the RLS is set to authenticated.
So it looks like you need an authenticated access token allow access to that table
But the API docs requests for anon key
The apikey is anon. Your authentication header is the user JWT.
this works as expected!
