supabase-js
supabase-js copied to clipboard
Realtime RLS API Call not Respecting `private: true` flag
Bug report
- [X] I confirm this is a bug with Supabase, not with my own application.
- [X] I confirm I have searched the Docs, GitHub Discussions, and Discord.
Describe the bug
There is more context here in this discord thread: https://discord.com/channels/839993398554656828/1287055628769951754/1287055628769951754
To summarize though, when using supabase-js
and following the docs for authorized real time broadcasts, only certain methods respect the { config: { private: true } }
flag. More specifically, the REST endpoint for prompting a broadcast as described here does not respect it:
https://supabase.com/docs/guides/realtime/broadcast?queryGroups=language&language=js#send-messages-using-rest-calls
A clear and concise description of what the bug is.
To Reproduce
Join a channel as a client with a given RLS policy that only allows for authenticated listeners:
const channelName = `project_${project.id}`;
const channel = supabase.channel(channelName, {
config: { private: true, broadcast: { self: true } },
});
channel.on("broadcast", { event: "test" }, (payload) =>
console.log("payload", payload),
);
channel.subscribe((status, err) => {
if (status === "SUBSCRIBED") {
console.log("Connected!", status);
} else {
console.log("realtime error", status);
}
});
RLS on realtime.messages
:
alter policy "Allow listening for broadcasts for authenticated users only"
on "realtime"."messages"
to authenticated
using (
(extension = 'broadcast'::text)
);
Trigger a message from a separate machine (in this case, I have a lambda function triggering it using the service key):
const channelName = `project_${project.data.id}`;
const channel = supabaseAdmin.channel(channelName, {
config: { private: true },
});
channel.send({
type: 'broadcast',
event: 'test',
payload: { message: 'Hi' },
})
The channel.send
function triggers a broadcast on a public channel when I expect it to trigger on a private channel given private: true
. This was confirmed to be an issue because the send
command has conditional logic based on being connected to the socket. Therefore, the workaround I provided below works because it waits until the subscription is connected first before sending.
Expected behavior
channel.send
should send on a private channel instead of a public channel when private: true
is set.
Screenshots
If applicable, add screenshots to help explain your problem.
System information
- OS: Windows WSL
- Browser (if applies) chrome
- Version of supabase-js: 2.45.4
- Version of Node.js: 22.8.0
Additional context
I have a work around that awaits
the subscription to the channel before sending.
const subscribedResult = await new Promise((resolve, reject) => {
channel.subscribe(async (status, err) => {
console.log("subscribing...");
if (status === "SUBSCRIBED") {
await channel.send({
type: "broadcast",
event: "test",
payload: { message: "Hi" },
});
resolve("success");
} else {
console.log("realtime error", status);
reject(err);
}
});
});