Admin Setup
This guide explains how to mark users as administrators in Supabase and how to write Row Level Security (RLS) policies that use that flag. The recommended approach is to store a simple is_admin boolean in a user's user_metadata, which is included in JWTs issued by Supabase.
Important: you cannot update the auth.users table directly with SQL. Update user_metadata via the Supabase Dashboard or the Admin API (using a service role key).
Recommended user_metadata shape
Add the following JSON to a user's user_metadata:
{
"is_admin": true
}
Option A — Dashboard (manual)
- Open the Supabase Dashboard → Auth → Users.
- Find the user and click Edit.
- Add
{"is_admin": true}to theuser_metadatafield and save.
Option B — Admin API (programmatic)
Use the Admin API or supabase-js admin helpers with your service role key. Example (Node):
import { createClient } from '@supabase/supabase-js';
const admin = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_SERVICE_ROLE_KEY
);
await admin.auth.admin.updateUserById(userId, {
user_metadata: { is_admin: true },
});
Refer to Supabase docs for the exact admin method name for the client version you use.
RLS example using JWT user_metadata
If your JWT contains user_metadata (the common Supabase setup), reference it directly in policies:
CREATE POLICY "Admins can manage rows"
ON public.your_table
FOR ALL
TO authenticated
USING (
(auth.jwt() -> 'user_metadata' ->> 'is_admin')::boolean = true
);
This method checks the is_admin flag in the JWT and is efficient because it avoids extra joins.
Alternative: check auth.users table
If you need to read the auth.users table, use auth.uid() to match the current user and verify their metadata:
USING (
EXISTS (
SELECT 1 FROM auth.users
WHERE auth.users.id = auth.uid()
AND (auth.users.user_metadata->>'is_admin')::boolean = true
)
)
Notes and best practices
- Keep admin flags minimal (a single boolean) to avoid complex permission logic in JWTs.
- Use the service role key only on trusted backends — never expose it to clients.
- After changing a user's
user_metadata, the user's JWT may need to be refreshed (re-login) to pick up new claims.
If you'd like, I can add a short troubleshooting section or link this page from the admin sidebar.