Home / Guides / Hiding the admin button isn't access control: protect admin routes properly

Hiding the admin button isn't access control: protect admin routes properly

In AI-built apps, admin pages are often protected only in the UI. How to enforce admin access where the data lives.

A common AI-generated pattern: if (user.isAdmin) showAdminButton(). The page or button disappears, but the data and actions behind it are still reachable by anyone who calls the API directly from DevTools.

Where the check must live

Example: Supabase admin-only table

create table public.admins (user_id uuid primary key references auth.users);
alter table public.admins enable row level security;  -- no policies: clients can't read or edit it

create policy "admins read all orders" on public.orders for select to authenticated
  using (exists (select 1 from public.admins a where a.user_id = (select auth.uid())));

Test it

Log in as a normal user, open DevTools → Network, copy an admin request and replay it (or open /admin directly). It should fail with 401/403 or return no rows.

Copy-paste into your AI builder
Find every admin-only page, action and query in this app. Enforce admin access server-side (RLS policies or server route checks using a role users cannot modify), not just by hiding UI. Then tell me how to test it as a non-admin user.

Related: RLS policy examples · Pre-launch checklist

Scan your app free

Paste your URL. ShipLatch checks for leaked keys, exposed /.env and /.git, and flags Supabase/Firebase so you know what to lock down. The free scan finds the issues; the $29 Fix Pack gives you fix prompts written for your app and re-scans that prove each fix worked.

Scan free at shiplatch.com → See the Fix Pack · $9 playbook

Want the whole pre-launch process in one place? Get App Security for Vibe Coders, our $9 PDF playbook.

More guides