Skip to content
Every tutorial here is 100% free — and always will be
LSLovableStudent

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.

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

  1. Store roles in a separate user_roles table (with columns like user_id, role), never as an editable column on profiles.
  2. Write row-level security policies on admin-only tables that check the role via a security definer function querying user_roles — never trust a role value sent from the client.
  3. Also add a front-end route guard for a clean UX (redirect non-admins away), but treat it as convenience, not security.
  4. 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?

Related questions

Website made, maintained and hosted by PromptSites.com

PromptSites logo