Row Level Security
Ce que tu vas apprendre
- Pourquoi une table exposée sans RLS est ouverte à tout le monde.
- Activer la RLS et écrire une politique par opération.
- Lier chaque recette à son auteur pour que lui seul puisse la modifier.
Le danger
La clé publishable est dans ton site. N'importe qui peut la copier et appeler l'API de ton projet avec elle, sans passer par ton site.
Sans protection, cette personne peut lire, modifier ou vider ta table recettes. La seule barrière est la base elle-même.
Row Level Security (RLS) est cette barrière. Quand elle est activée, une ligne n'est accessible que si une règle l'autorise.
Activer la RLS
Le Table Editor du tableau de bord l'active à la création d'une table. En SQL, c'est à toi :
alter table recettes enable row level security;
Une fois activée et sans aucune politique, la table refuse tout. Un select renvoie une liste vide, un insert est rejeté.
C'est le bon point de départ : tu ouvres ensuite uniquement ce qui doit l'être.
Une politique
Une politique (policy) est une règle attachée à une table. Elle précise l'opération, le rôle concerné et la condition. Voici la lecture ouverte à tous les visiteurs :
create policy "Tout le monde peut lire les recettes"
on recettes for select
to anon, authenticated
using ( true );
Les rôles sont anon (visiteur sans compte) et authenticated (connecté). La condition using filtre les lignes déjà présentes. Ici true laisse tout passer.
Lier une recette à son auteur
Pour qu'un utilisateur ne touche qu'à ses recettes, la table doit savoir à qui appartient chaque ligne :
alter table recettes
add column user_id uuid references auth.users (id);
La colonne user_id pointe vers la table des comptes. Le client la remplit avec l'identifiant de la personne connectée, lu dans user.sub (cours 04) :
await supabase
.from('recettes')
.insert({ titre: 'Crêpes', user_id: user.value?.sub })
La politique d'insertion ci-dessous vérifie que cette valeur est bien la tienne : tricher est impossible.
Écrire, modifier, supprimer
Une politique par opération, réservée aux connectés :
create policy "Ajouter ses recettes"
on recettes for insert
to authenticated
with check ( (select auth.uid()) = user_id );
create policy "Modifier ses recettes"
on recettes for update
to authenticated
using ( (select auth.uid()) = user_id )
with check ( (select auth.uid()) = user_id );
create policy "Supprimer ses recettes"
on recettes for delete
to authenticated
using ( (select auth.uid()) = user_id );
Deux mots à distinguer :
| Clause | Teste | S'applique à |
|---|---|---|
using | Les lignes qui existent déjà | select, update, delete |
with check | Les lignes écrites ou modifiées | insert, update |
Écrire (select auth.uid()) plutôt que auth.uid() seul est une recommandation de la documentation : Postgres calcule la valeur une fois par requête.
Un update a aussi besoin d'une politique de lecture qui laisse voir la ligne. Ici la politique de lecture ouverte à tous la fournit.
Tester
- Ouvre le site sans être connecté : tu vois les recettes, mais un
insertéchoue. - Connecte-toi avec un compte A et ajoute une recette : elle apparaît avec ton
user_id. - Connecte-toi avec un compte B et tente de supprimer la recette de A : la suppression ne touche aucune ligne.
Le troisième test est le plus important. Il prouve que la règle tient même si quelqu'un contourne ton interface.
La clé secrète
La clé secrète appartient au rôle service_role, qui contourne la RLS. Aucune politique ne la retient.
Elle ne doit donc jamais figurer dans une page, un composant ou un fichier du dépôt. Supabase la refuse d'ailleurs si une requête vient d'un navigateur.
À retenir
- La clé publishable est publique : la RLS est ce qui protège réellement les données.
- Active la RLS sur chaque table exposée, avec
alter table ... enable row level security. - Sans politique, une table avec RLS refuse tout.
- Écris une politique par opération (
select,insert,update,delete) et limite-la au rôle utile. usingteste les lignes existantes,with checkles lignes écrites.- Compare toujours à
auth.uid()pour que chacun ne touche qu'à ses lignes. - La clé secrète contourne la RLS : serveur uniquement, jamais commitée.
Pour aller plus loin
Sources officielles
Ensuite
Authentification
Inscrire et connecter des utilisateurs avec e-mail et mot de passe, lire la session et protéger une page.
Stockage et temps réel
Envoyer des photos de recettes dans le stockage Supabase avec des règles d'accès, et recevoir les changements de la base en direct.
- Projet
- Lignes de code
- Niveau
- Cave
- Appartement
- Supabase
- Pièce
- 5/7
- Plan n°
- supabase/05.row-level-security