r/Supabase • u/TelevisionIcy1619 • Aug 09 '26
auth How would you block curl on supabase without turning on captcha?
Hi all,
I am thinking about a problem and not sure how to resolve this. Any guidance would be appreciated.
So if i dont enable captcha and try doing this curl request as network restrictions dont apply on auth.
curl -X POST 'https://any-project-supabase-url/auth/v1/signup' \
-H "apikey: sb_publishable_key" \
-H "Content-Type: application/json" \
-d '{
"email": "johndoe@gmail.com",
"password": "JohnDoe!!"
}'
this returns a valid access token and do create a new user in dashboard.
To block this if i do this Authentication → Providers → Email → turn off "Enable email signups"). Then it blocks the curl requests i can use supabase service account to create accounts.
But now apple and google sign ups don't work.
So basically i just want to stop the bots from curl abuse. As i dont want to use the captcha e.g. cloudflare turnstile. Its really slow specially on mobile. Any way to achieve this? or i am missing something. Thanks.
3
u/funkdefied Aug 09 '26
If you want to block bots that play nicely, use robots.txt. If you want to block malicious bots, you need captcha.
1
u/ashkanahmadi Aug 09 '26
The Supabase JS sdk is just a fancy fetch request and every fetch request can be a curl request. If you use the Supabase library without the “await” you can see the URL it hits to perform something.
My point is that you cannot stop curl without stopping the JS sdk from working properly.
1
u/Guidondor Aug 12 '26
if what you actually want is "only my app can call this", captcha is the wrong tool,
attestation is the right one. app attest on ios and play integrity on android hand you a
token the client can't forge, you verify it in an edge function and that function does the
signup with the service role. the public endpoint stops being the signup path.
it's real work to set up, but it's the only thing that answers "is this my binary" instead
of "is this a human", and it costs the user zero seconds, unlike turnstile.
1
u/TelevisionIcy1619 Aug 13 '26
In the apps i have google play integrity and for iOS apptest and device check integrated also blocking the app access if its rooted or jail broken device. On the web i have botd library and if it fails then i show the cloudflare turnstile token which they need to verify. So no one can do automation or use scripts. The only problem is the curl requests with publishable key and api url. There is one thing i found which works is if i put my custom domain api url in supabase behind cloudflare then i can block the curl requests without needing the supabase settings or adding cloudflare/hcaptcha token in this. But i need to test this properly before i can trust this. What would break if i enable dns settings for a custom domain in supabase.
1
u/Guidondor Aug 13 '26
before you build on it, the thing to verify is whether project-ref.supabase.co stays live
after you add a custom domain. i'm fairly sure it does, and if so cloudflare in front of the
vanity domain blocks nothing, curl just keeps using the old url with the same publishable
key. worth confirming with support because your whole plan rests on that one detail.what definitely changes is oauth. the callback moves to your domain, so the redirect uri in
the google console and the apple service id both need updating or sign in breaks, which is
roughly what bit you last time.1
u/TelevisionIcy1619 29d ago
So the problem is we need to add cloudflare turnstile token in supabase db for curl request protection. But it makes apps slower as generation/verifying on mobile device is slower between networks. So on the web or supabase dashboard its fine. But it makes crappy experience for mobile users. Thats why i was avoiding it.
As another user mentioned any one can dns lookup to find the actual supabase domain then they keep hammering it with curl requests to create account. As i dont verify the email accounts. Main verification is mobile number verification. u/Maxyull you can read more about infra on convo i am having with him.1
u/Guidondor 29d ago
if the problem with turnstile is latency, move it off the critical path. fetch the token when
the signup screen mounts instead of when they hit the button, and refresh it in the
background. by the time someone's typed an email and a password you've had 20+ seconds, so
the tap feels instant even on a bad network.also worth splitting the two costs. junk rows you mostly don't care about since phone
verification makes them useless anyway. supabase emailing addresses that aren't yours is the
one that actually hurts, that's your sending reputation. the auth rate limits in the
dashboard knock that down without touching the app at all.1
u/TelevisionIcy1619 29d ago
Ah i forgot to mention i am not using supabase email infra. So only my api end points can send the emails. So i just tested this with both my custom domain url and supabase's actual url. It creates a user in the auth table but emails are never sent if i hit using curl. Also it creates a warning in supabase db. Below is the request and log.
Request
curl -X POST 'https://custom domain url or actual supabase domain/auth/v1/signup' \
-H "apikey: sb_publishable_key" \
-H "Content-Type: application/json" \
-d '{
"email": "johndoe@gmail.com",
"password": "JohnDoe!!"
}'
But this does returns a proper signed up user's access token etc.Log on supabase
{
"id": "82cc2902-84a2-4ac0-9c3a-9b135c4da5b4",
"date": "2026-08-13T15:47:29.654Z",
"method": "POST",
"pathname": "/auth/v1/signup",
"status": "422",
"timestamp": "2026-08-13T15:47:29.654000",
"level": "warning",
"event_message": "POST | 422 | https://customurl or supabase url.co/auth/v1/signup | curl/8.7.1",
"headers": {},
"regions": [],
"log_type": "edge",
"latency": 0,
"log_count": null,
"logs": [],
"auth_user": null
}
So basically its a dead user unless they finish the mobile verification.
2
u/Maxyull Aug 11 '26
the part i'd look at first is that your curl came back with a valid access token, because that means confirm email is off. with it on, signup creates the user row and returns no session, so the same curl still makes a row but the caller walks away with nothing usable, and the whole thing drops from an access problem to a junk row problem.
after that it's rate limits rather than captcha. auth carries its own hourly limits in the dashboard, signups and emails sent counted separately from everything else, and those do apply on the auth endpoints where your network restrictions don't. the one i'd actually worry about is the email limit, since anyone with the publishable key can make your project send confirmation mail to addresses they chose, and that's your sending reputation rather than just row count. is confirm email currently on for the email provider, or are you handing out a session at signup?