Skip to content

RLS Policy Violation (403 Forbidden) Despite Correct User ID and Permissions #35153

Description

@YutaOkoshi

Bug report

  • I confirm this is a bug with Supabase, not with my own application.
  • I confirm I have searched the Docs, GitHub Discussions, and Discord.

Hello Supabase Team,

I am encountering a persistent issue with Row Level Security (RLS) policies on my ideas table, resulting in a 403 Forbidden error (PostgREST error code 42501: new row violates row-level security policy for table "ideas") when attempting to UPDATE a row (specifically, performing a logical delete by setting deleted_at), even though all checks seem to pass.

Context:

  • Table: public.ideas
  • Operation: PATCH /rest/v1/ideas?uid=eq.<idea_uid> (from Supabase JS client update method) to set deleted_at = NOW().
  • Target Row: uid = '1b046deb-76ec-8168-afa8-f5364f00e612', user_uid = 'd1dc7a43-6a95-426f-9c3c-144742edef9f'
  • Authenticated User: auth.uid() = 'd1dc7a43-6a95-426f-9c3c-144742edef9f'

Troubleshooting Steps Taken:

  1. Client-Side Authentication Verified: Used supabaseClient.auth.getUser() right before the update call, confirming the client is authenticated with the correct user ID (d1dc7a43-...).
  2. Request Headers Verified: Inspected the PATCH request headers in browser dev tools. The Authorization: Bearer <token> header is present, and the JWT payload correctly contains "sub": "d1dc7a43-...". The token is valid.
  3. Data Integrity Verified: Confirmed that the target row (uid = '1b046deb-...') in the ideas table indeed has user_uid = 'd1dc7a43-...'.
  4. Table Permissions Verified: Confirmed using information_schema.role_table_grants that the authenticated role has UPDATE privileges on the public.ideas table.
  5. RLS Policy Simplified (UPDATE):
    • Initially, the UPDATE policy had both USING (auth.uid() = user_uid) and WITH CHECK (auth.uid() = user_uid). The 403 error occurred.
    • Crucially, I modified the UPDATE policy to remove the WITH CHECK clause, leaving only USING (auth.uid() = user_uid). The 403 Forbidden error still persists even with this simplified policy.
  6. Other RLS Policies: Checked pg_policies - INSERT has WITH CHECK (auth.uid() = user_uid), SELECT has USING (((auth.uid() = user_uid) OR (shared = true)) AND (deleted_at IS NULL)). No other potentially conflicting policies found.
  7. Triggers: Only have a standard trigger BEFORE UPDATE to set updated_at = NOW(). This trigger does not modify user_uid.
  8. Database Webhooks/Functions: No webhooks or functions are triggered by updates on the ideas table.

Current RLS Policies on public.ideas:

[
  {
    "schemaname": "public",
    "tablename": "ideas",
    "policyname": "Users can only create their own ideas",
    "permissive": "PERMISSIVE",
    "roles": "{public}",
    "cmd": "INSERT",
    "qual": null,
    "with_check": "(auth.uid() = user_uid)"
  },
  {
    "schemaname": "public",
    "tablename": "ideas",
    "policyname": "Users can only update their own ideas (no check)", // Note: WITH CHECK removed
    "permissive": "PERMISSIVE",
    "roles": "{public}",
    "cmd": "UPDATE",
    "qual": "(auth.uid() = user_uid)", // USING clause
    "with_check": null // No WITH CHECK
  },
  {
    "schemaname": "public",
    "tablename": "ideas",
    "policyname": "Users can view their own non-deleted ideas and shared non-delet",
    "permissive": "PERMISSIVE",
    "roles": "{public}",
    "cmd": "SELECT",
    "qual": "(((auth.uid() = user_uid) OR (shared = true)) AND (deleted_at IS NULL))",
    "with_check": null
  }
]

Problem Summary:

Despite verifying client authentication, token validity, data integrity, table permissions, and simplifying the RLS UPDATE policy to only USING (auth.uid() = user_uid), the operation is still blocked by RLS (403 Forbidden, code 42501). This suggests a potential issue within the Supabase backend regarding how auth.uid() is evaluated or compared in the USING clause for this specific UPDATE operation.

Could you please investigate why the RLS policy might be failing even when all apparent conditions are met?

Thank you for your assistance.

System information

  • OS: macOS 15.3.2(24D81)
  • package.json
    • "@supabase/supabase-js": "^2.47.10",
    • @supabase/auth-helpers-nextjs@0.10.0
    • "next": "^14.2.8",
  • Node.js Version18.x
  • Browser: Arn
    • Version1.91.0 (61725)
    • Chromium Engine Version 135.0.7049.96

Screenshots

If applicable, add screenshots to help explain your problem.

Additional context

Add any other context about the problem here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions