How I Set Up Policies in Supabase (Step-by-Step Guide)

How I Set Up Policies in Supabase (Step-by-Step Guide)
When I first started using Supabase, I realized that setting up policies is essential for controlling who can access and modify data. Without policies, anyone could read or change my database, which is a big security risk.
Here’s a simple breakdown of how I set up Row Level Security (RLS) in Supabase.
Step 1: Enable Row Level Security (RLS)
Supabase uses Row Level Security (RLS) to manage data access. By default, RLS is disabled when you create a new table, meaning anyone can access the data.
To enable RLS:
- Open your Supabase dashboard
- Go to the table you want to secure
- Click on Security → Enable RLS
Once RLS is enabled, no one can access the table until you create policies.
Step 2: Setting Up Policies for Different Users
I needed to set up access for three types of users:
- Anonymous users (public access)
- Authenticated users (logged-in users)
- Service role (backend access only)
1. Anonymous Users (Read-Only Access)
I wanted anonymous users to be able to read data but not modify it. To do this, I created a policy:
This means:
- Anyone can read the data
- No one can insert, update, or delete without authentication
In the frontend, I initialized Supabase with the anon key (public key):
2. Authenticated Users (Access Their Own Data)
For logged-in users, I wanted them to:
- View and modify only their own data
- Not access other users' data
So, I created this policy:
This means:
- auth.uid() gets the authenticated user's ID from Supabase
- The query only returns rows where user_id matches the logged-in user's ID
To ensure that the frontend always includes the user's token, I set up Supabase with global headers:
With this setup, every request automatically includes the user's authentication token.
3. Service Role (Full Backend Access)
The service role key bypasses all policies and is meant for backend use only.
To allow full access in the backend, I used:
Important:
- The service role key should never be used in the frontend because it can override all security policies.
Final Thoughts
Once I set up these policies, my database was secure and well-structured. Here’s a quick summary:
User Type Permissions Policy | ||
Anonymous Users | Read-only | using (true); |
Authenticated Users | Can access their own data | using (auth.uid() = user_id); |
Service Role | Full access (backend only) | No policy restrictions |
With this setup:
- Public users can only read data
- Logged-in users can only access their own data
- The backend has full control
Setting up policies correctly ensures data security and structured access control in Supabase.