How do I protect admin pages?
Last checked 31 Aug 2026
Short answer
Check the user's role server-side (in the database query or Edge Function) using a dedicated user_roles table — hiding an admin link in the navigation menu doesn't stop someone visiting the URL directly.
Why hiding a link isn't protection
Front-end route guards (redirecting a non-admin away from /admin) improve the experience for ordinary users but don't stop someone who knows or guesses the URL and has valid credentials from a lower-privilege account — the actual data has to be protected at the source.
The correct pattern
- Store roles in a separate
user_rolestable (with columns likeuser_id,role), never as an editable column onprofiles. - Write row-level security policies on admin-only tables that check the role via a
security definerfunction queryinguser_roles— never trust a role value sent from the client. - Also add a front-end route guard for a clean UX (redirect non-admins away), but treat it as convenience, not security.
- For admin actions that call an Edge Function, check the role inside the function itself before doing anything privileged.
A prompt that helps
Add an admin role check to the admin dashboard: store roles in a separate user_roles table, verify the role server-side in both the page's data queries and any Edge Functions it calls, and redirect non-admins from the route.
What usually goes wrong
A role column added to profiles for convenience means a user can potentially update their own profile row to role: admin unless a very specific RLS policy prevents it — this is exactly why roles must live in their own table with tightly scoped update permissions. See /questions/can-users-access-other-users-information and /questions/how-do-i-check-supabase-rls for the underlying RLS mechanics.
Sources
Was this answer helpful?
Next step
Related questions
- GuideHow to Add User Roles and PermissionsAdmin, editor and member roles done safely — stored separately from user profiles so they cannot be escalated.
- AnswerHow do I make Lovable perform a security review without changing anything?Explicitly tell Lovable to run in read-only review mode — ask it to report findings only and not touch any code, then decide what to fix yourself.
- AnswerHow do I stop bots?Add a CAPTCHA (e.g. Cloudflare Turnstile) to public forms, validate inputs server-side, and rate-limit submissions — client-side-only checks like a hidden field are easy for real bots to bypass.
- AnswerHow do I prevent spam registrations?Verify email addresses on sign-up, add a CAPTCHA to the registration form, rate-limit sign-up attempts per IP, and check the token server-side before creating an account.