Supabase Auth 在 Next.js middleware 中的 6 個常見錯誤及修正方法
Supabase Auth dans le middleware Next.js : 6 erreurs fréquentes (et comment les corriger)
這份指南整理了在 Next.js App Router 的 middleware 使用 Supabase Auth 時,6 類常見錯誤及修正方法。建議改用 @supabase/ssr、把更新後的 Cookie 寫回回應、建立客戶端後立即呼叫 getUser(),並在伺服器端避免以 getSession() 驗證。
Le middleware de Next.js est l'endroit naturel pour rafraîchir la session Supabase et rediriger les visiteurs non connectés. C'est aussi là que naissent les bugs les plus agaçants : déconnexions aléatoires, boucles de redirection, pages protégées qui s'affichent quand même. Voici les six erreurs que l'on rencontre le plus souvent avec l'App Router.
1. Utiliser encore les anciens « auth helpers »
Le paquet @supabase/auth-helpers-nextjs est déprécié. La méthode actuelle passe par @supabase/ssr, qui fournit createServerClient (serveur, middleware) et createBrowserClient (composants client). Mélanger les deux paquets dans un même projet donne des cookies incompatibles et des sessions qui disparaissent.
npm install @supabase/supabase-js @supabase/ssr
2. Ne pas renvoyer les cookies rafraîchis
Quand le jeton d'accès expire, Supabase le renouvelle et écrit de nouveaux cookies. Si le middleware ne les recopie pas sur la réponse, le navigateur garde l'ancien jeton et l'utilisateur est déconnecté au bout d'une heure. Le client doit écrire à la fois sur la requête et sur la réponse :
// middleware.ts
import { createServerClient } from '@supabase/ssr'
import { NextResponse, type NextRequest } from 'next/server'
export async function middleware(request: NextRequest) {
let response = NextResponse.next({ request })
const supabase = createServerClient(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
{
cookies: {
getAll() {
return request.cookies.getAll()
},
setAll(cookiesToSet) {
cookiesToSet.forEach(({ name, value }) => request.cookies.set(name, value))
response = NextResponse.next({ request })
cookiesToSet.forEach(({ name, value, options }) =>
response.cookies.set(name, value, options))
},
},
}
)
const { data: { user } } = await supabase.auth.getUser()
if (!user && request.nextUrl.pathname.startsWith('/dashboard')) {
const url = request.nextUrl.clone()
url.pathname = '/login'
return NextResponse.redirect(url)
}
return response
}
3. Glisser du code entre createServerClient et getUser()
La documentation de Supabase insiste : n'exécutez pas de logique entre la création du client et l'appel à auth.getUser(). Un await sur autre chose à cet endroit peut faire perdre le rafraîchissement du jeton, et l'on obtient des déconnexions difficiles à reproduire. Créez le client, appelez getUser(), puis seulement ensuite décidez de la redirection.
4. Faire confiance à getSession() côté serveur
getSession() lit la session depuis les cookies sans la revalider : un cookie modifié à la main passerait le contrôle. Dans le middleware, les Server Components et les Route Handlers, utilisez getUser(), qui vérifie le jeton auprès de Supabase Auth. Gardez getSession() pour le client, où il sert surtout à l'affichage.
5. Un matcher trop large
Sans configuration, le middleware tourne sur chaque requête, y compris les fichiers statiques et les images optimisées. Chaque appel ajoute un aller-retour vers Supabase et ralentit tout le site. Excluez ce qui n'a pas besoin de session :
export const config = {
matcher: [
'/((?!_next/static|_next/image|favicon.ico|.*\\.(?:svg|png|jpg|jpeg|gif|webp)$).*)',
],
}
Et si vous redirigez vers /login, vérifiez que /login ne redirige pas à son tour : c'est la cause classique de la boucle infinie.
6. Croire que le middleware protège les données
Le middleware protège la navigation, pas la base. Une requête faite directement avec la clé anon contourne entièrement vos redirections. Activez Row Level Security sur chaque table exposée et écrivez des politiques basées sur auth.uid(). Considérez le middleware comme une amélioration de l'expérience utilisateur, et RLS comme la vraie barrière de sécurité.
En résumé
@supabase/ssr à la place des anciens helpers, cookies recopiés sur la réponse, getUser() appelé immédiatement et utilisé côté serveur, un matcher qui ignore les fichiers statiques, et RLS partout. Avec ces six points, l'authentification se comporte de la même façon en local et en production sur Vercel.
Transparence : cet article est écrit par l'équipe de Massvai, un générateur d'applications par IA qui crée des projets full-stack Next.js, Supabase et Vercel. Les conseils s'appliquent à n'importe quel projet, que vous utilisiez notre outil ou non.
來源:DEV Community · dev.to