0

I'm building a website using Next.js, NextAuth, and Supabase. I'm not using Supabase's built-in auth — instead, I manage a custom users table and generate custom JWTs using NextAuth during sign-in.

In the JWT, I set the sub claim to the user's UUID from my own users table, and use this to authenticate against Supabase's RLS. Here's a simplified version of the policy I'm using:

CREATE POLICY "Allow users to select their own messages"
ON messages FOR SELECT
USING (auth.uid()::text = user_id::text);

Direct select queries using the authenticated Supabase client work as expected and return only the current user's messages.

Realtime subscriptions (.channel().on('postgres_changes')) connect successfully but do not receive any data after new messages are inserted.

Additional context:

  • I signed the JWT using the same secret set in SUPABASE_JWT_SECRET.
  • I confirmed that the client Supabase instance includes the custom JWT in the Authorization: Bearer header.
  • The payload includes:
    {
      "sub": "<user-uuid>",
      "aud": "authenticated",
      "role": "authenticated",
      "email": "<user-email>",
      "exp": <timestamp>
    }
    
  • Realtime is enabled on the messages table.
  • My client uses Supabase’s JS SDK v2 with .channel().

Question:

Why is Supabase Realtime not enforcing RLS correctly with a custom JWT, even though direct queries work?
How can I make Realtime subscriptions respect RLS policies using auth.uid() when using a custom users table and manually generated JWT? Or is it other problem causing the issue?

To test whether this is an RLS issue, I temporarily added a policy that allows all users to select any rows:

CREATE POLICY "temp_test_realtime"
ON messages FOR SELECT
USING (true);

After enabling this, Realtime subscriptions started receiving data correctly for new inserts.

So it seems the issue is related to how Supabase Realtime interacts with RLS when using a custom JWT (not Supabase Auth).

New contributor
ergs0204 is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.

0

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.