This is a template, that enables Supabase users to quickly create multi-tenant application with role-based security access.
I've started this project because I believe, that multi-tenancy is an important feature for small startups. It is very common to have a project where you want to host multiple tenants in the same database. And allowing them to have users, with different levels of access is another important feature.
The third reason for having this project is that I wanted to make sure that everything is covered with appropriate test cases.
- There are tenants
- All tables must be referring the tenant table and set the appropriate RLS policy
- The security implements a simple RBAC scheme
- There is an enumerated type
app_permissions
:all
tenant_members.assign
roles.edit
roles.assign
profiles.edit
- Permissions are assigned to roles
- Roles are assigned to groups
- There is an enumerated type
- All permission must be scoped - within the current tenant
- There are some special claims copied to
auth.users.raw_app_meta_data
perms[]
- an array of permissionstenant_id
- the tenant to which this user is assignedtenant_access
- controls access if the user can "read" or "write" the tenants table
- All fields from
user_profile
are copied toauth.users.raw_user_meta_data
- The public profile
user_profiles
is optional. If you don't need it, removed it from migrations.
- Users can be assigned to only one tenant.
- You cannot assign tenant admin (tenant_access) normally. You have to use a database admin/superuser account for that.
This project is based on the wonderful custom-claims work. As such it has the same drawback. One particular one, that you should be aware of is that permissions are set inside JWT claims. So the permission is removed the user will keep having the permission until the JWT claim expires.
One significant difference is that the roles and permissions are managed by a table, not by calling the set_claim
function. Roles update is achieved through the usage of triggers.
Go to demo
folder.
- run
npm install
(only once) - Configure your instance with the command below. Just make sure to change the key.
cat << EOF > .env.local
VITE_SUPABASE_URL=http://localhost:54321
VITE_SUPABASE_ANON_KEY=<your_key>
EOF
- run
npm run dev
- run
open http://localhost:5173/
- Related materials
- https://www.tangramvision.com/blog/hands-on-with-postgresql-authorization-part-2-row-level-security
- https://www.thenile.dev/blog/multi-tenant-rls
- https://blog.mansueli.com/using-custom-claims-testing-rls-with-supabase
- https://medium.com/@jimmyruann/row-level-security-custom-permission-base-authorization-with-supabase-91389e6fc48c
- https://dev.to/supabase/supabase-custom-claims-34l2
- Useful resources
- Future improvements