| name | supabase-rls |
| description | Supabase Row Level Security policies. Use when creating RLS policies, securing tables, or implementing multi-tenant data isolation. |
Supabase Row Level Security (RLS)
Enable RLS on Table
-- Always enable RLS
ALTER TABLE projects ENABLE ROW LEVEL SECURITY;
Common Policy Patterns
User Can Only See Own Data
CREATE POLICY "Users view own data"
ON projects FOR SELECT
TO authenticated
USING (auth.uid() = user_id);
User Can Insert Own Data
CREATE POLICY "Users insert own data"
ON projects FOR INSERT
TO authenticated
WITH CHECK (auth.uid() = user_id);
User Can Update Own Data
CREATE POLICY "Users update own data"
ON projects FOR UPDATE
TO authenticated
USING (auth.uid() = user_id)
WITH CHECK (auth.uid() = user_id);
User Can Delete Own Data
CREATE POLICY "Users delete own data"
ON projects FOR DELETE
TO authenticated
USING (auth.uid() = user_id);
Multi-Tenant Patterns
Team-Based Access
-- Users can see projects in their teams
CREATE POLICY "Team members view projects"
ON projects FOR SELECT
TO authenticated
USING (
team_id IN (
SELECT team_id FROM team_members
WHERE user_id = auth.uid()
)
);
Role-Based Access
-- Check user role for admin access
CREATE POLICY "Admins can do everything"
ON projects FOR ALL
TO authenticated
USING (
EXISTS (
SELECT 1 FROM user_roles
WHERE user_id = auth.uid()
AND role = 'admin'
)
);
Service Role Bypass
For server-side operations that need to bypass RLS:
import { createClient } from '@supabase/supabase-js';
// This bypasses RLS - use carefully!
const supabaseAdmin = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.SUPABASE_SERVICE_ROLE_KEY!, // Not ANON key!
{ auth: { persistSession: false } }
);
Testing Policies
-- Test as specific user
SET request.jwt.claim.sub = 'user-uuid-here';
-- Run query and check results
SELECT * FROM projects;
-- Reset
RESET request.jwt.claim.sub;
Security Checklist
- RLS enabled on all tables with user data
- Service role key only on server, never client
- Policies cover all operations (SELECT, INSERT, UPDATE, DELETE)
- No policies use functions that could be exploited
- Test policies with different user roles