Supabase provides a special function in Postgres, auth.uid(), which extracts the user’s UID from the JWT. This is especially useful when creating Policies.
But since it looks like that relies on the request:
CREATE OR REPLACE FUNCTION auth.uid()
RETURNS uuid
LANGUAGE sql
STABLE
AS $function$
select nullif(current_setting('request.jwt.claim.sub', true), '')::uuid;
$function$
perhaps
create policy "Users can update their own profiles."
on profiles for update using (
auth.uid() = id
);
would be
create policy "Users can update their own profiles."
on profiles for update using (
current_user_id = id
);
given the above Prisma example when setting current_user_id ahead of the query?
I guess I’ll have to figure out a good way of testing this – will try this week.
Following this thread with much interest. As already stated, RBAC is very important building apps today. I am working in the innovation sector and we are building new apps on a monthly basis. Having a toolset like Supabase in combo with RedwoodJS is something that gives us the necessary boost that I am really looking forward to.
What we’re wanting to try is to see if that role security can also extend into the Postgres level in policies rather than just in the service business logic api side.
For Supabase, you’d want to set your “app roles” in app_metadata as a collection of roles:
Sorry for the confusion with my statement about the “importance” of RBAC. I fully understand that redwood already has RBAC in place. I already tried using it with Supabase with success.
For that matter I was following the cookbook and enriching the user object with roles and for my case also with the uuid from the users table in supabase like so:
With this approach security is enforced on the service side rather than the Postgres side directly. Or in other words, hitting the the Supabase API directly would still return “unfiltered” data since no RLS is enforced. Enabling RLS and writing security rules like this create policy "Individuals can view their own todos." on todos for select using (auth.uid() = user_id); would not really do any good, since RW is always operating with a service token.
If I understood you correctly, you are trying to address this problem by finding a way combining RLS with RBAC, correct?
Yes, that’s correct - most/all implementations have sort of been done as you have, though with Supabase I do setup the trigger from auth.user to publuc.User and then keep roles also in the auth schema and set on the auth.user in raw_app_metadata. This saves all the db lookups get getUserRequest.
Also, when using Supabase be sure to use Connection Pooling.
Think this was just a misunderstanding in that when I thought you asked about “any updates” on RLS.
@saendu Thanks for the example. I have implemented similar however I am having trouble extracting and using the accountId. What I would like to do is navigate users to an account page after logIn based on their accountId – see code snippets.
Should accountId be part of the currentUser object?
@dthyresson Thanks. The query works, however, passing the values to the enriched object doesn’t. I’m OK to leave as is for the time being but get that it would be better to do it in a single query.
I noticed in Docs - Authentication : RedwoodJS Docs that there is an Auth Provider Specific Integration section for most providers but not yet Supabase. If you know of an example or can provide any guidance, that would great. I can update the docs once clear.
Hi @0x1a4f7d58 Actually I think that’s exactly how you would update the user metdata:
But, you can still to this in a service.
Create SDL for a Mutation that defines the attributes you want in userMetadata (you could do JSON, but better probably if you set). Call that mutation maybe updateUserMetadata()
In a userMetadata service, create you update method
That method should
requireAuth so you make sure they are logged in
create an instance of the supabase client but instead of using the non key or the superadmin service role key, use the currentUser’s token. That will say that the supabase client can only act on that user’s info
then supabase.auth.update() the input data from your mutation
You should be able to get the bearer token using context[1].token
Not 100% on this but in your cell handling after the metadata update, instead of showing information from the graphql result, you would want to show the userMetadata from useAuth() hook.
What I wonder, though, is if you will need to force Supabase to re-authenticate and update the user metadata is has stored in its session.
You can get the client from the useAuth() hook as well and force a re-auth via await reauthenticate().