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.
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_roledans 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
anonou 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_roledoit 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 :
- l'utilisateur appelle une route serveur
- cette route verifie qu'il a bien le droit de faire l'action
- le serveur utilise
service_rolepour executer l'operation sensible - 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 :
- Cherchez
SUPABASESERVICEROLE_KEYdans le repo. - Verifiez que les fichiers qui l'utilisent sont bien cote serveur.
- Verifiez qu'aucune variable secrete n'est prefixee par
NEXTPUBLIC. - Controlez les imports des clients Supabase dans les composants
"use client". - 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
Lire ensuite sur le meme sujet
Ces liens renforcent le cocon semantique du blog et aident Google a comprendre le sujet principal de l'article.
