Replies: 4 comments
-
|
Beta Was this translation helpful? Give feedback.
-
|
Hey — thanks for the detailed write-up. The manual SQL-editor repro is genuinely helpful, because it tells us exactly where the problem is not. Since
A 3-step check that pins it down — the key idea is to look at the exact token on the failing request, not the one you think you're sending: Step 1 — Decode the on-the-wire token. DevTools → Network tab → click the failing Step 2 — Confirm the platform accepts that exact token. curl https://<project-ref>.supabase.co/auth/v1/user \
-H "apikey: <your publishable or anon key>" \
-H "Authorization: Bearer <the exact token from step 1>"
Step 3 — See exactly what Postgres receives (the decisive test). create or replace function public.whoami()
returns jsonb language sql stable as $$
select jsonb_build_object(
'uid', auth.uid(),
'role', auth.role(),
'claims', current_setting('request.jwt.claims', true)
);
$$;curl -X POST https://<project-ref>.supabase.co/rest/v1/rpc/whoami \
-H "apikey: <your publishable or anon key>" \
-H "Authorization: Bearer <the exact token from step 1>" \
-H "Content-Type: application/json" -d '{}'
In ~95% of these reports the answer is step 1 or step 3: the One more thing that helps rule out a platform issue: which client are you using to send the request — |
Beta Was this translation helpful? Give feedback.
-
|
Hey — thanks for the detailed write-up. The manual SQL-editor repro is genuinely helpful, because it tells us exactly where the problem is not. Since
A 3-step check that pins it down — the key idea is to look at the exact token on the failing request, not the one you think you're sending: Step 1 — Decode the on-the-wire token. DevTools → Network tab → click the failing Step 2 — Confirm the platform accepts that exact token. curl https://<project-ref>.supabase.co/auth/v1/user \
-H "apikey: <your publishable or anon key>" \
-H "Authorization: Bearer <the exact token from step 1>"
Step 3 — See exactly what Postgres receives (the decisive test). create or replace function public.whoami()
returns jsonb language sql stable as $$
select jsonb_build_object(
'uid', auth.uid(),
'role', auth.role(),
'claims', current_setting('request.jwt.claims', true)
);
$$;curl -X POST https://<project-ref>.supabase.co/rest/v1/rpc/whoami \
-H "apikey: <your publishable or anon key>" \
-H "Authorization: Bearer <the exact token from step 1>" \
-H "Content-Type: application/json" -d '{}'
In ~95% of these reports the answer is step 1 or step 3: the One more thing that helps rule out a platform issue: which client are you using to send the request — (For maintainers: opened #47161 adding a troubleshooting doc for this pattern.) |
Beta Was this translation helpful? Give feedback.
-
|
This looks like the same root cause as the other post-JWT-signing-key reports: PostgREST can't verify the token's signature, so it silently downgrades the request to the The thing to check is whether the access token your app sends is actually verifiable by this project's current keys:
What makes your report notable is that it reproduces on a brand-new project with fresh tokens. If a just-issued token's |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Project ref: pywexoexxcxrrrxfvqgf (also reproduced identically on jdpoayuhktbbljdkxwqv)
Summary: Authenticated REST requests fail RLS because auth.uid() returns NULL at runtime, even though the request carries a valid Authorization: Bearer access token with the correct sub. This happens on a brand-new project with a fresh schema and reproduces on a second project.
Symptom: POST /rest/v1/grupy → 403, Proxy-Status: PostgREST; error=42501, body {"code":"42501","message":"new row violates row-level security policy for table "grupy""}. Policy: with check (wlasciciel_id = auth.uid()). The wlasciciel_id sent equals the user's auth UID exactly (34f4d443-1fc5-4745-877d-8b89461ad33e), confirmed in Authentication → Users. The Authorization header contains the user's session token (distinct from the apikey) with the correct sub.
Proof it is NOT the schema/app — running in the SQL editor with claims set manually works:
begin;
select set_config('request.jwt.claims','{"sub":"34f4d443-1fc5-4745-877d-8b89461ad33e","role":"authenticated"}', true);
set local role authenticated;
select auth.uid(); -- returns 34f4d443-... correctly
insert into public.grupy (nazwa, wlasciciel_id)
values ('Test','34f4d443-1fc5-4745-877d-8b89461ad33e'); -- succeeds, passes RLS
rollback;
So auth.uid() and the policies are correct. The failure is purely that live PostgREST requests do not propagate JWT claims into the DB session (request.jwt.claims is empty at runtime → auth.uid() NULL).
JWT config / things already tried (no change):
Request: Please investigate why JWT claims are not propagated to PostgreSQL for authenticated requests on this project despite valid tokens. This appears tied to the new JWT Signing Keys and reproduces on a fresh project.
Beta Was this translation helpful? Give feedback.
All reactions