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.

Icône de calendrier
Débutant
4 chapitres

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 :

  1. 🔐 Sécurité implémentée directement dans la BDD (pas dans le code backend)
  2. ⚡ 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 :

copié !
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 RLSConséquence
😱 RLS désactivéPas de sécurité – accès public/total à tous
🚫 RLS activé sans policyAccès interdit à tous
RLS activé avec policyAccè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 :

copié !
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 descriptif
  • ON : la table concernée par la politique de sécurité
  • AS : type de policy (PERMISSIVE par défaut, ou RESTRICTIVE 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 ou ALL 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 bas
  • USING : 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 :

ClauseQuand elle s’appliqueEffet
USINGSELECT, UPDATE, DELETEFiltre les lignes visibles ou modifiables. Si condition fausse → invisible.
WITH CHECKINSERT, UPDATEVérifie les nouvelles données. Si condition fausse → rejet de la requête.

Voici un exemple pour mieux comprendre :

copié !
-- 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 utilisateurs
  • auth.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

copié !
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

copié !
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

copié !
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

copié !
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

copié !
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

copié !
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.

copié !
-- 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 et WITH 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ôleClé API associéeUtilisationPortée / Privilèges
anonPublishable KeyFrontend / visiteurs anonymesAccès en lecture limité selon les RLS. Pas de privilèges d’écriture sensibles.
authenticatedPublishable Key + JWTUtilisateurs connectésAccès en lecture et écriture limité selon les RLS. Privilèges accordés sur ses propres données.
service_roleSecret KeyBackend sécurisé / tâches critiquesAccè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.