Supabase › Sécurité et RLS Policies
Apprenez à sécuriser vos tables Postgres grâce au Row Level Security (RLS). Créez des policies efficaces et protégez vos projets Supabase.
Le Row Level Security (RLS) est un pilier essentiel de la sécurité dans Supabase. Voyons comment activer et configurer vos policies pas à pas.
Qu’est-ce que le RLS ?
Le Row Level Security (RLS
) est une fonctionnalité de PostgreSQL qui permet de contrôler l’accès aux lignes d’une table, en fonction de l’utilisateur qui effectue la requête.
Contrairement aux permissions classiques (qui s’appliquent sur une table entière), le RLS agit au niveau granulaire : vous pouvez définir précisément quelles lignes un utilisateur peut lire, insérer, modifier ou supprimer.
🤔 Pourquoi Supabase l’utilise ?
Supabase repose sur le système de gestion de base de données PostgreSQL natif. Plutôt que de réinventer un système d’autorisations maison, Supabase exploite directement le RLS intégré à Postgres.
Les RLS présentent des avantages majeurs :
- 🔐 Sécurité implémentée directement dans la BDD (pas dans le code backend)
- ⚡ Fonctionne automatiquement avec l’API REST et GraphQL de Supabase.
Voici quelques cas d’usage typiques afin que vous compreniez l’intérêt des RLS :
- Applications avec espace utilisateur : un utilisateur peut voir ses propres infos privées et le contenu public des autres utilisateurs.
- Applications multi-tenant : chaque client/organisation a ses données, mais elles partagent la même base.
- Rôles différents : admins avec accès complet, utilisateurs avec accès restreint.
- Données sensibles : restreindre l’accès aux informations personnelles (RGPD).
- Etc.
Activer RLS sur une table
Si vous avez laissé l’option cochée lors de la création de votre table, le RLS est déjà activé.
Sinon, vous pouvez l’activer à tout moment dans le dashboard Supabase, en allant dans l’onglet Table Editor
, puis en sélectionnant votre table, ou même en exécutant la commande SQL suivante :
ALTER TABLE nom_table ENABLE ROW LEVEL SECURITY;
Notez que cela va avoir pour effet d’interdire tout accès à la table, tant qu’aucune politique de sécurité n’est définie.
Voici un récapitulatif des différents scénarios de sécurité selon l’état du RLS :
État RLS | Conséquence |
---|---|
😱 RLS désactivé | Pas de sécurité – accès public/total à tous |
🚫 RLS activé sans policy | Accès interdit à tous |
✅ RLS activé avec policy | Accès contrôlé selon les règles définies |
Créer des RLS policies
Structure d’une RLS policy
Vous l’aurez compris, une politique de sécurité (« security policy ») est une règle qui définit qui peut faire quoi sur une table.
Voici comment créer une policy avec une commande SQL :
CREATE POLICY <"nom_de_la_policy">
ON <nom_de_la_table>
AS <PERMISSIVE|RESTRICTIVE>
FOR <SELECT|INSERT|UPDATE|DELETE|ALL>
TO <role>
USING (expression)
WITH CHECK (expression);
CREATE POLICY
: label descriptifON
: la table concernée par la politique de sécuritéAS
: type de policy (PERMISSIVE
par défaut, ouRESTRICTIVE
pour des cas avancés de combinaison de policies)FOR
: le type de requête concerné par la politique de sécurité (SELECT
,INSERT
,UPDATE
,DELETE
ouALL
pour toutes les actions)TO
: le rôle PostgreSQL concerné (ex :authenticated
,anon
,service_role
ou un rôle personnalisé) - cette partie sera détaillée plus basUSING
: condition pour filtrer une ligne (SELECT
/UPDATE
/DELETE
)WITH CHECK
: condition pour valider l’insertion (INSERT
) ou la modification (UPDATE
) d’une ligne
L’expression dans USING
ou WITH CHECK
est une condition SQL qui doit retourner TRUE
pour que l’accès soit autorisé. Nous en verrons des exemples plus bas.
Quand utiliser USING
ou WITH CHECK
?
USING
et WITH CHECK
peuvent être utilisés ensemble ou séparément, selon le type d’action que vous souhaitez contrôler.
Retenez que leur rôle dépend du type d’action (FOR
) que vous souhaitez contrôler.
Voici un tableau récapitulatif pour clarifier leur usage :
Clause | Quand elle s’applique | Effet |
---|---|---|
USING | SELECT , UPDATE , DELETE | Filtre les lignes visibles ou modifiables. Si condition fausse → invisible. |
WITH CHECK | INSERT , UPDATE | Vérifie les nouvelles données. Si condition fausse → rejet de la requête. |
Voici un exemple pour mieux comprendre :
-- L'utilisateur peut lire uniquement ses propres posts
using (user_id = auth.uid())
-- L'utilisateur ne peut insérer un post qu'en son nom
with check (user_id = auth.uid())
user_id
est la clé étrangère vers la table des utilisateursauth.uid()
est une fonction spéciale de Supabase qui retourne l’ID de l’utilisateur connecté effectuant la requête
Quelques exemples de RLS policies
Voici quelques exemples courants de policies que vous pourriez créer.
1. Lecture (SELECT
)
Autoriser uniquement l’utilisateur connecté à voir ses propres données
CREATE POLICY "users can view own profile"
ON profiles
FOR SELECT
USING (id = auth.uid());
id
est la clé primaire de la table profiles
qui correspond à l’ID de l’utilisateur.
Autoriser tout le monde à voir les données publiques
CREATE POLICY "anyone can view public posts"
ON posts
FOR SELECT
USING (is_public = true);
is_public
représente une colonne booléenne dans la table posts
qui indique si un post est public ou privé.
2. Insertion (INSERT
)
Empêcher d’insérer une ligne au nom d’un autre utilisateur
CREATE POLICY "users can insert their own posts"
ON posts
FOR INSERT
WITH CHECK (user_id = auth.uid());
user_id
est une clé étrangère vers la table des utilisateurs.
3. Mise à jour (UPDATE
)
Limiter la modification de ses propres posts
CREATE POLICY "users can update their own posts"
ON posts
FOR UPDATE
USING (user_id = auth.uid())
WITH CHECK (user_id = auth.uid());
USING
empêche de cibler un post d’un autre user, et WITH CHECK
garantit que le user_id
ne sera pas changé.
Changer son pseudo mais pas celui des autres
CREATE POLICY "users can update their own profile"
ON profiles
FOR UPDATE
USING (id = auth.uid())
WITH CHECK (id = auth.uid());
4. Suppression (DELETE
)
Supprimer uniquement ses propres posts
CREATE POLICY "users can delete their own posts"
ON posts
FOR DELETE
USING (user_id = auth.uid());
Tester les accès
Une fois vos policies définies, il est essentiel de les vérifier en conditions réelles afin de s’assurer qu’aucune donnée sensible n’échappe à vos contrôles.
Supabase offre plusieurs manières de tester ses RLS.
Depuis la rubrique SQL Editor
Depuis l’éditeur SQL, il est possible d’exécuter vos requêtes avec différents rôles (anon
, authenticated
) pour voir ce qui est autorisé ou refusé.
De manière plus brute, vous pouvez utiliser la commande SQL SET ROLE
pour simuler un autre rôle directement dans Postgres.
-- Simuler le rôle anonyme
set role anon;
select * from posts;
Avec l’API REST/GraphQL
Vous pouvez également tester la validité de vos policies en utilisant l’API REST ou GraphQL de Supabase comme détaillé dans le chapitre dédié à la manipulation d’une base de données Supabase.
Ces appels API peuvent être effectués via des outils comme Postman ou Insomnia, pour une meilleure organisation de vos requêtes.
Tests automatisés
Une autre approche, plus professionnelle, consiste à intégrer des tests avec par exemple Jest ou Vitest qui valident que l’accès est correctement restreint selon les rôles.
Bonnes pratiques RLS
D’après la documentation officielle de Supabase, voici quelques recommandations qu’il est utile d’avoir à l’esprit afin de bien gérer vos politiques de sécurité RLS :
- Toujours activer RLS : par défaut, tout est public si RLS est désactivé.
- Utiliser
USING
etWITH CHECK
ensemble pour éviter les contournements lors des mises à jour de données (UPDATE
). - Préférez les conditions simples et lisibles : un RLS compliqué est difficile à maintenir.
- Documentez vos policies : chaque règle devrait avoir un but clair et une convention de nommage explicite (ex. « users can update own profile », « admins can delete any post », etc.).
Gestion des rôles
Supabase fournit trois rôles principaux, associés à une clé API avec des privilèges spécifiques. Ces clés définissent ce que vos utilisateurs ou votre backend peuvent faire.
Rôle | Clé API associée | Utilisation | Portée / Privilèges |
---|---|---|---|
anon | Publishable Key | Frontend / visiteurs anonymes | Accès en lecture limité selon les RLS. Pas de privilèges d’écriture sensibles. |
authenticated | Publishable Key + JWT | Utilisateurs connectés | Accès en lecture et écriture limité selon les RLS. Privilèges accordés sur ses propres données. |
service_role | Secret Key | Backend sécurisé / tâches critiques | Accès complet, ignore les RLS. À utiliser uniquement côté serveur pour opérations sensibles (migrations, batch processing, etc.). |
En maîtrisant les RLS Supabase, vous contrôlez précisément qui peut voir ou modifier vos données et vous renforcez la sécurité de vos applications.