0

I am trying to set up RLS to a table in Supabase that will only allow the authenticated user to UPDATE their row on users table. I have opted to use Supabase on my server rather than the front-end. My current workflow is as follows:

  1. Client requests a OTP via email
  2. User is emailed an OTP
  3. OTP is entered into the Client
  4. OTP is verified on the server
  5. If verified UPDATE the users row in the users table with new session details
  6. Return the current user details to the Client

Here is the code that is failing:

const { error } = await supabase
  .from('users')
  .update({
    access_token: session.access_token,
    refresh_token: session.refresh_token,
    expires_at: session?.expires_at || 0
  })
  .eq('user_id', user.id)
  .single();

Here is the table structure: enter image description here

When I run const user = supabase.auth.user(); I am showing the correct user that has a user.id that matches the rows user_id column of the row I want to UPDATE.

Without RLS set up this workflow is working perfectly. Anything I try fails. Below are the three RLS that I have tried that should work.

  1. Checking if user exists WHERE auth.uid() = users.user_id in both USING and CHECK enter image description here

  2. Added auth.uid() = user_id in both USING and CHECK enter image description here

  3. The weirdest one of the all, set true in both USING and CHECK enter image description here

Here are screen shots of the uuid on the auth.users table and user_id on the users table: enter image description here enter image description here

Attempted this from one of the answers and it is still failing: enter image description here

Here is the error response I am receiving from Supabase: enter image description here

Craig Howell
  • 1,114
  • 2
  • 12
  • 28
  • To make this easier to debug please setup these policies individually, so setup the INSERT, SELECT, UPDATE, DELETE policies separately and not try to use one to rule them all. I think the issue is on the SELECTing of the results from the UPDATE. So create a policy for SELECT which just returns true and one for UPDATE with `uid() = user_id` and see what happens. – Andrew Smith Aug 07 '22 at 23:19
  • I agree with your statement in part Andrew but there is an issue with `UPDATE` statement in Supabase that when utilized actually uses the `SELECT` statement as well meaning if you do not have both set up it will error out unless you add a `{ returning: 'minimal' }` to the `UPDATE` request. Just trying to get this working then I will will dial it in for specific statements. – Craig Howell Aug 08 '22 at 12:36

1 Answers1

1

This is not very well documented yet, but signed in users have authenticated role, and not anon role, so changing the target role to authenticated should fix it. When in doubt, just leave the target roles blank, which will apply the RLS on all roles.

Set RLS on authenticated

dshukertjr
  • 15,244
  • 11
  • 57
  • 94
  • 1
    Swapped out `anon` with `authenticated` but still receiving the same error. I have added more information to the question to show the id's do match and a picture of trying your solution. – Craig Howell Aug 07 '22 at 14:09
  • @CraigHowell Could you share the error message that you are getting? – dshukertjr Aug 07 '22 at 14:18
  • 1
    @CraigHowell Also, have you tried not specifying any target roles at all? – dshukertjr Aug 07 '22 at 14:24
  • I have added the error response to the question. I just removed tried leaving the target role blank and it is now working. Does this mean this is applied to all roles, even the service role? – Craig Howell Aug 07 '22 at 15:10
  • @CraigHowell glad to hear that it is working now. Service role will always bypass row level security, so no worried there! – dshukertjr Aug 07 '22 at 22:31