Rork security guide
How to secure a Rork mobile app's Supabase backend
Treat the Supabase publishable key in your Rork app as public, because it ships inside the iOS or Android binary. Turn on RLS with ownership policies for every table, make edge functions that hold private keys check their callers, and test policy changes before you apply them, since Rork Cloud changes go live at once.
Last updated
How do I connect Supabase to a Rork app?
When an app needs data, Rork shows a Create Rork Cloud card with a Connect my Supabase option. Rork also documents Firebase. For Supabase you have three paths.
- Pick Connect my Supabase on the Create Rork Cloud card.
- Or ask Rork: "Add a Supabase backend to my app".
- Or set it up by hand: copy the project's URL and Publishable key from Supabase and paste them into Rork with the prompt "Connect Supabase".
Why must every table have RLS in a Rork app?
The publishable key ships inside the binary, and anyone can extract it. With the key and the URL, a client can call every table the anon and authenticated roles can reach. RLS is what limits each user to their own rows.
-- Tables in public without RLS. This must return no rows.
select c.relname
from pg_class c
join pg_namespace n on n.oid = c.relnamespace
where n.nspname = 'public' and c.relkind = 'r' and not c.relrowsecurity;alter table public.workouts enable row level security;
create policy "workouts: owner reads" on public.workouts
for select to authenticated
using ((select auth.uid()) = user_id);
create policy "workouts: owner inserts" on public.workouts
for insert to authenticated
with check ((select auth.uid()) = user_id);
create policy "workouts: owner updates" on public.workouts
for update to authenticated
using ((select auth.uid()) = user_id)
with check ((select auth.uid()) = user_id);How do I test a policy before it goes live?
Rork Cloud has no preview step, so test in a transaction that rolls back. Create the policy, switch to a user and count rows, then roll back. Nothing persists until you run it for real.
begin;
set local role authenticated;
select set_config('request.jwt.claims', '{"sub":"00000000-0000-0000-0000-000000000001","role":"authenticated"}', true);
select count(*) from public.workouts; -- only this user's rows
rollback;How should Rork edge functions handle private keys?
Edge functions are where private API keys and payment webhooks belong, never in the app. Supabase requires a valid JWT for each call by default. A function deployed with verify_jwt = false accepts calls from anyone.
- Keep verify_jwt on for functions the app calls.
- For a payment webhook that must accept calls without a user JWT, verify the provider's signature inside the function.
- Keep private keys in the function's secrets, never in the app's code.
# Functions that anyone can call without a signed-in user.
grep -n "verify_jwt = false" supabase/config.tomlWhat should I do after transferring Rork Cloud to my Supabase organization?
- Note that the transfer is one-way and keeps the same URL, data and keys.
- Rotate any secret key that may have been exposed before the transfer.
- Run the RLS query above and the Supabase Security Advisor.
- Connect the project to Supahound for the daily posture scan.
Frequently asked questions
- Is the Supabase key inside my Rork app a secret?
- No. The publishable key maps to the anon or authenticated role and is meant to be public. Never put a secret key into a Rork app, because anything in the binary is readable.
- Can I use Firebase instead of Supabase with Rork?
- Rork documents Firebase as well as Supabase and Rork Cloud. Supahound monitors Supabase projects only.
- Can I undo a Rork Cloud transfer?
- No. The transfer to your Supabase organization is one-way. Plan key rotation and RLS checks for the day you transfer.