Here you see that the confirmation that the user w...
# help
h
Here you see that the confirmation that the user was added to the users/auth table, and then the error that occurred trying to create the player @User
o
I can see that the message isn't really helpful... one option is to try to debug it manually from the SQL editor. you can change the role manually to
authenticated
using:
Copy code
sql
-- this sets the role for the transaction only
SET role authenticated;

-- try to insert the player manually
insert into players (user_id, name) values ('id', 'some_name');
I believe this will give you a better message and easier to debug than from the client side
try to re-create the policy and make sure
auth.role()
is called instead of
role()
alone
I remember this was an issue I encountered before @User
h
Ugh - I'm sending off
ALTER POLICY "Special " ON public.players USING ((auth.role() = 'authenticated'::text)) WITH CHECK ((auth.role() = 'authenticated'::text));
but it always comes back subsequently with the auth removed
o
that's weird. try to copy the statement and run it from the SQL editor (it shouldn't remove the schema reference)
g
The Policy UI does not display the auth part even if you create in the UI or SQL with it. I don't think setting role to authenticated will work. The function role() is looking at the jwt or user table itself, I'm pretty sure.
For sure you can't use postgres role... create or replace function auth.role() returns text as $$ select nullif(current_setting('request.jwt.claim.role', true), '')::text;
I believe your problem is no jwt for some reason. As I said on github check if you have a jwt authentication header in your insert call.
h
Just checked, the api calls are done with the SDK and the apikey and authorization headers ar epresent
o
that's correct and I totally missed it -- one should also update the config in addition to the role:
Copy code
sql
-- to avoid bypassing the RLS 
SET role authenticated; 
-- for the policy to receive the correct value (maybe you need to set it to null afterwards)
select set_config('request.jwt.claims.role', 'authenticated');
g
Your policies look correct.
h
function set_config(unknown, unknown) does not exist
g
If you turn off RLS does the client code work?
h
yes, then all is fine
g
Then it is something wrong with the jwt still, my guess. As long as you have both select using and insert with check, should be good if the jwt is authorised
o
sorry I was writing that from memory:
Copy code
sql
select set_config('request.jwt.claims.role', 'authenticated', true); -- true means for the transaction only, false for the session
g
Since it works with out RLS the actual insert command/data should be fine (and should not generate policy error anyway if wrong)
What are your auth email confirmation settings (not sure it matters though if not email confirmed yet) when you make the insert call.
o
That may not work for newer versions of PostgreSQL -- here's an alternative way that helps in debugging:
Copy code
sql
SELECT set_config('request.jwt.claims', jsonb_build_object('role', 'authenticated')::jsonb::text, true)::text;
for debugging, I just created the following table and policies:
Copy code
sql
create table test (
  id text,
  value text
);

alter table public.test enable ROW LEVEL SECURITY;

CREATE POLICY "Enable insert for authenticated users only" 
ON public.test 
FOR INSERT WITH CHECK (
  auth.role() = 'authenticated'
);

CREATE POLICY "Enable select for authenticated user"
ON public.test
FOR SELECT USING (
  auth.role() = 'authenticated'
);
When I set
role()
instead of
auth.role()
-- I get an error
function role() does not exist
(in the local studio, it should show
auth.role()
in the UI -- at least recent version using the cli). Running the following:
Copy code
sql
set role authenticated;
insert into test values ('1', '1');
gives the following error:
Copy code
sql
new row violates row-level security policy for table "test"
On the other hand, running the following:
Copy code
sql
set role authenticated;
SELECT set_config('request.jwt.claims', jsonb_build_object('role', 'authenticated')::jsonb::text, true)::text; 
insert into test values ('1', '1');
gives the following results:
Copy code
Success. No rows returned
I'm sharing this just as a way to debug ... If you're using the cli for local development, maybe try upgrading to the newest version.
g
@User Can you confirm you currently still have a separate select policy? Client insert will not work unless you set returning: 'minimal' if your select policy is also not met.
h
thanks @User - I'm doing everything from the web UI as I know nothing about SQL
But,
Copy code
SET role authenticated;
SELECT set_config('request.jwt.claims', jsonb_build_object('role', 'authenticated')::jsonb::text, true)::text; 

insert into players (user_id, name) values ('....', 'some_name');
got a success
g
@User I just tested your code from the client, with email confirm on and it does not pass auth role in, there is no session until you respond to email. I get your same error.
h
This is the fetch version of the request the browser made - this is what Chrome gives me
Copy code
fetch("https://xyz.supabase.co/rest/v1/players?columns=%22user_id%22%2C%22name%22", {
    "headers": {
        "accept": "*/*",
        "accept-language": "en-GB,en;q=0.9,en-US;q=0.8,nl;q=0.7,fr;q=0.6,es;q=0.5",
        "apikey": "abc123",
        "authorization": "Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9......",
        "cache-control": "no-cache",
        "content-profile": "public",
        "content-type": "application/json",
        "pragma": "no-cache",
        "prefer": "return=representation",
        "sec-ch-ua": "\" Not;A Brand\";v=\"99\", \"Google Chrome\";v=\"97\", \"Chromium\";v=\"97\"",
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": "\"macOS\"",
        "sec-fetch-dest": "empty",
        "sec-fetch-mode": "cors",
        "sec-fetch-site": "cross-site",
        "x-client-info": "supabase-js/1.29.1"
    },
    "referrer": "http://localhost:3000/",
    "referrerPolicy": "strict-origin-when-cross-origin",
    "body": "[{\"user_id\":\"abc123\",\"name\":\"HB\"}]",
    "method": "POST",
    "mode": "cors",
    "credentials": "include"
});
>
g
Do you have email confirm on?
h
yes, if I have to wait for that then I will need to rewrite my flow
g
With email confirm on there is no session data returned from signup and you get the 403 error on insert. The session contains the important jwt information. With email confirm off, signUp without that returns session immediatly.
That is your problem
Most people do the signup and use a trigger on the auth.user insert to write to their extra public table. You can pass in user meta data in the signup call.
h
yes, I swtiched off the confirmation and it logs in - thank you and @User so much!!!!!!!!
g
I would use the trigger meta data approach if you want to not wait around for the email confirm.
but it does not sya what happens ot the extra
data
I can try to play around with that
end of my day though (Europe), so that'll be for next weekend
g
@User so you have it when you get back to it. The main part is at the bottom of this:
h
👍 💯