Reputation: 1
When a user in my application claps virtually in the theatre, it will send a request for increasing a count by 1 in Supabase.
Currently, I am using signInWithPassword
for authentication and the update RLS policy is enabled for authenticated users only.
However, with the approach, the user can open the Chrome console, copy the request headers, including apikey
and authentication
, and update the count by sending additional requests, e.g. by using Postman.
What should I do to prevent this? I tried to set the JWT expiration time to 1 sec and successfully acheived the goal, but this solution sounds strange.
Upvotes: 0
Views: 648
Reputation: 1
I encountered the exact same issue as you .
The only workaround I could think of is to build an API middle layer. In fact, they are HTTP API on AWS API Gateway + Lambda. This would create a middle layer where you could control the inputs and hide how your backend is working.
Because if an attacker were to discover your supabase query, that's it, reverse engineering becomes straightforward for data leaks or other operations.
PS: I chose HTTP API over REST for performance reasons. Therefore, I cannot implement the Web Application Firewall (WAF) to provide further protection, unless I set up a CloudFront distribution and then WAF. However, this would make the query longer. Currently, the lambda function is written in Python 3.11, very short, only calling supabase. It is deployed in Paris. The supabase is hosted in Frankfurt, so the network distance is optimal.
It takes approximately 450ms to fetch a single entry from supabase and up to 1.9s for 3900 entries (14 columns) on the first run only. Then AWS caches the query and the time goes down to 800ms.
Tested from Supabase, it takes 338ms for the 3900 entries (14 columns) on the first run. 361ms for 1entry
Upvotes: 0
Reputation: 18612
You have to make a trade-off between simplicity and security.
If you want to make it so that you can limit how many claps a user can send, or how often they can send claps, etc., you have to keep every record of claps that every user sends. You can have a claps
table that holds user_id
to hold who clapped, clapped_at
to hold when the clap happened, and maybe a post_id
or whatever suites your application to hold what the clap was for. This way, when a user attempts to clap, you can check to see if it's a valid clap or not. Supabase makes it easy to count rows, so getting the total claps isn't a huge issue.
You can use row level security or RLS to control how the user can "clap" in your application.
For example, you can set the following RLS policies to allow all users to access the claps
table, but only allow insert for their own claps. This prevents the users from updating or deleting any claps. You can alter this behavior to whatever suites your application.
-- Create a sample claps table
-- This table assumes that there is a `posts` table and a `users` table
create table if not exists public.claps (
post_id uuid references public.posts on delete cascade not null,
user_id uuid references public.users on delete cascade not null,
created_at timestamp with time zone default timezone('utc' :: text, now()) not null,
PRIMARY KEY (post_id, user_id)
);
-- Enable RLS for `claps` table
alter table public.claps enable row level security;
create policy "Any users can view the claps table"
on claps for select
using ( true );
create policy "Allow users to insert their own clap"
on claps for insert
with check ( auth.uid() = user_id );
Upvotes: 0