-
-
Notifications
You must be signed in to change notification settings - Fork 198
Description
I'm encountering a persistent issue that I hope you can help me resolve. Despite numerous tests, my Supabase table continues to reject inserts under Row-Level Security (RLS), even though all policy conditions seem valid. Here's a detailed breakdown.
✅ Goal
I’m building a Flutter quiz app where players log in anonymously and their progress is saved in a table named players_secure. The table uses UUIDs as id fields and RLS is enabled.
🧪 Desired Behavior
When an anonymous user logs in and fills in their name, country, and PIN, their data should be inserted into the players_secure table using:
insert {
id: auth.uid(),
name: ..., country: ..., pin: ...
}
The ID is set manually from auth.uid() (not auto-generated).
❌ The Problem
The insert consistently fails with:
PostgrestException:
new row violates row-level security policy for table "players_secure"
code: 42501
details: Forbidden
This occurs only when RLS is enabled. If I disable RLS, the insert works fine.
🧩 Setup Details
Table: players_secure
- id – UUID (Primary Key, Not Nullable, Default: NULL)
- RLS: ✅ Enabled
- Insert is performed with id = auth.uid() manually
- Other columns: name (text), country (text), pin (text), score (int), etc.
🔐 Policies
Current INSERT Policy:
CREATE POLICY "Allow own insert via id = auth.uid()"
ON public.players_secure
FOR INSERT
TO anon, authenticated
WITH CHECK (
id = auth.uid()
);
✅ This policy matches all official examples for anon + RLS inserts.
SELECT and UPDATE Policies are also set correctly and tested separately. All use auth.uid() = id. They are not blocking my queries.
✅ Diagnostics
I ran an explicit insert using SQL with id = auth.uid() — it worked correctly. But the same insert fails via Flutter when RLS is enabled.
What has been ruled out (works fine)
Flutter/Supabase setup and authentication
The app is correctly initializing Supabase, calling signInAnonymously() in main.dart before any database calls, and sending a valid JWT to PostgREST.
Network calls and JWT headers
I consistently see non-null Access Tokens and matching “Auth UID” values in my debug logs, and when RLS is turned off entirely, the .insert(...) calls succeed.
Table schema and Dart code
The players_secure table structure (UUID id column plus name, country, pin, score, etc.) and my Dart insert logic all match up—no changes are needed there.
RLS disabled on the table allows full reads and writes, confirming nothing else in my setup is mis-configured.
The remaining “sticky point”
All symptoms point to the INSERT policy’s check expression never truly matching my user’s UUID, even after multiple attempts to cast types. In particular:
Role mismatch was fixed by widening the policy to both anon and authenticated, so now the correct Supabase role is being targeted.
Type mismatch between the JWT’s subject (auth.uid(), a text value) and the id column (a UUID) means a straight comparison (auth.uid() = id or id = auth.uid()) always fails.
Attempts to cast —
auth.uid()::uuid = id
id::text = auth.uid()
— have been applied via SQL Editor but, when inspected through Supabase Studio, still show the old, un-cast form. Even direct queries (pg_get_expr) report the legacy check, so the cast never “sticks.”
I confirmed via pg_get_expr(...) that Postgres itself is still storing the old expression.
🧪 Other Info
- Table has no default for id, so Supabase does not auto-insert UUID.
- Authentication page allows anonymous sign-ins and sign-ups.
- App logs show auth.uid() is valid and present.
- If fallback policies are added (e.g., allow all inserts), insert works — but that defeats RLS.
🧠 Hypothesis
It seems Supabase accepts the token and UID, but the insert fails only when it goes through the Flutter client, even though the token is valid and policies are correct.
🔄 Temporary Workaround
I am currently disabling RLS to continue development and re-enabling it later. Not ideal.
🙏 Request
Can you help me determine:
- Is this a known issue with RLS and anonymous auth?
- Are there additional session claims or headers the Flutter client must include?
- Is there a best practice for using auth.uid() in a manually inserted UUID field when RLS is on?
Thank you for your time — any guidance would be much appreciated.
Happy to provide logs, policies, or simplified test cases if needed.