← Blog
Technique5 min de lecture16 juin 2026

Next.js + Supabase: comment utiliser service_role sans l'exposer

La cle service_role ne doit jamais partir dans le navigateur. Voici la bonne architecture pour l'utiliser proprement avec Next.js.

PN
Paul Noorman
Fondateur, OurPlan
Next.js + Supabase: comment utiliser service_role sans l'exposer

La cle service_role simplifie beaucoup de choses dans un projet Supabase. Elle permet des operations admin, des scripts serveur, des migrations de donnees, ou des taches de back-office. Mais elle a une regle non negociable : elle ne doit jamais partir dans le navigateur.

Supabase le dit tres clairement dans sa documentation API keys : n'exposez jamais service_role publiquement, et ne l'utilisez jamais dans un browser, meme en local.

Pourquoi cette cle est si sensible

La cle service_role donne des privileges eleves sur votre projet. Elle est faite pour du code controle par le developpeur :

  • route handlers serveur
  • jobs planifies
  • scripts d'administration
  • back-office avec controles d'acces stricts

Si cette cle arrive dans le front, dans une bundle ou dans un repo public, le probleme n'est pas "potentiellement embetant". Le probleme est immediat. Vous donnez un acces beaucoup trop large a votre base et a vos ressources.

Le piege le plus frequent avec Next.js

Le piege classique ressemble a cela :

  • on veut faire une action admin rapidement
  • on reuse le meme client Supabase partout
  • on met la cle service_role dans une variable d'environnement mal placee
  • on importe ce client dans un composant qui finit cote client

Dans Next.js, la frontiere serveur/client est tres importante. Un fichier marque avec "use client" ou importe depuis un composant client ne doit jamais embarquer une logique qui depend d'un secret serveur.

Le bon principe est simple : la cle service_role ne vit que dans du code execute serveur.

Le bon schema dans un projet Next.js

Vous avez en pratique deux familles de clients :

1. Le client public ou utilisateur

Il utilise :

  • l'URL Supabase publique
  • une cle anon ou publishable

Il sert au parcours normal :

  • lecture publique
  • actions utilisateur connecte
  • tout ce qui doit respecter les policies RLS du vrai utilisateur

2. Le client admin ou serveur

Il utilise :

  • l'URL Supabase
  • la cle service_role

Il sert uniquement a des endroits maitrisés :

  • route handlers
  • server actions si elles restent vraiment cote serveur
  • scripts de maintenance
  • outils d'administration avec verification en amont

Un exemple de separation saine

Le pattern propre ressemble a ceci :

// client public
createClient(process.env.NEXT_PUBLIC_SUPABASE_URL!, process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!)

// client serveur createClient(process.env.NEXTPUBLICSUPABASEURL!, process.env.SUPABASESERVICEROLEKEY!) ```

Et surtout :

  • le client public peut etre importe cote navigateur
  • le client service_role doit rester dans un module serveur

Dans un projet Next.js, cela veut dire en pratique :

  • pas d'import dans un composant "use client"
  • pas d'utilisation dans une action declenchee depuis le front sans garde serveur claire
  • pas de variable NEXTPUBLIC... pour un secret serveur

L'erreur qui coute cher

Il existe une erreur tres simple mais tres grave : prefixer un secret avec NEXTPUBLIC.

Dans Next.js, tout ce qui commence par NEXTPUBLIC est pense pour etre disponible cote client. Donc si vous mettez votre service_role la-dedans, vous changez un secret serveur en information potentiellement exposee.

Si vous avez le moindre doute, verifiez vos variables d'environnement et vos imports tout de suite.

Que faire pour une action admin cote produit

Si votre produit a besoin d'une action admin, la bonne methode n'est pas de donner la cle au navigateur. La bonne methode est :

  1. l'utilisateur appelle une route serveur
  2. cette route verifie qu'il a bien le droit de faire l'action
  3. le serveur utilise service_role pour executer l'operation sensible
  4. la reponse retournee au client reste minimale

Ce schema garde la logique critique dans un endroit que vous controlez.

Le cas des cles modernes Supabase

La documentation Supabase recommande aujourd'hui de passer vers les cles publishable et secret quand c'est possible. Mais le principe de securite ne change pas :

  • cle publique = front possible
  • cle secrete ou privilegiee = serveur uniquement

Autrement dit, meme si votre projet evolue vers les nouvelles cles, la discipline reste la meme.

Comment auditer votre projet vite

Faites cette mini checklist :

  1. Cherchez SUPABASESERVICEROLE_KEY dans le repo.
  2. Verifiez que les fichiers qui l'utilisent sont bien cote serveur.
  3. Verifiez qu'aucune variable secrete n'est prefixee par NEXTPUBLIC.
  4. Controlez les imports des clients Supabase dans les composants "use client".
  5. Testez qu'une action sensible passe toujours par une verification serveur en amont.

Si une de ces etapes n'est pas propre, il faut corriger avant d'ajouter d'autres features.

Un bon reflexe d'equipe

Le meilleur garde-fou est d'avoir deux modules clairement nommes :

  • un client public
  • un client admin

Et de poser une regle d'equipe tres simple : le client admin ne s'importe jamais dans du code client.

Cette regle est plus utile qu'un long document de securite que personne ne relit.

Ce qu'il faut retenir

service_role est un outil serveur, pas un outil front.

Si vous respectez la frontiere serveur/client dans Next.js, cette cle devient tres utile. Si vous la brouillez, vous ouvrez un risque severe pour la base, les comptes et les donnees du projet.

La bonne architecture n'est pas compliquee : un client public pour l'utilisateur, un client admin pour le serveur, et aucune confusion entre les deux.

Sources officielles