Modèles Next.js
Version : Vérifiez
package.jsonpour la version du SDK — voir la skillclerkpour la table des versions. Les différences Core 2 sont notées inline avec des callouts> **Core 2 ONLY (skip if current SDK):**.
Pour la configuration de base, voir la skill clerk-setup.
De Quoi Avez-Vous Besoin ?
| Tâche | Référence |
|---|---|
Auth serveur vs client (auth() vs hooks) |
references/server-vs-client.md |
| Configurer le middleware (public-first vs protected-first) | references/middleware-strategies.md |
| Protéger les Server Actions | references/server-actions.md |
| Auth sur les routes API (401 vs 403) | references/api-routes.md |
| Mettre en cache les données auth (user-scoped caching) | references/caching-auth.md |
Références
| Référence | Description |
|---|---|
references/server-vs-client.md |
await auth() vs hooks |
references/middleware-strategies.md |
Public-first vs protected-first, proxy.ts (Next.js <=15: middleware.ts) |
references/server-actions.md |
Protéger les mutations |
references/api-routes.md |
401 vs 403 |
references/caching-auth.md |
User-scoped caching |
Modèle Mental
Server vs Client = APIs d'authentification différentes :
- Server :
await auth()depuis@clerk/nextjs/server(async !) - Client : hook
useAuth()depuis@clerk/nextjs(sync)
Ne les mélangez jamais. Les Server Components utilisent les imports serveur, les Client Components utilisent les hooks.
Propriétés clés de auth() :
isAuthenticated— booléen, remplace le pattern!!userIdsessionStatus—'active'|'pending', pour détecter les tâches de session incomplètesuserId,orgId,orgSlug,has(),protect()— inchangées
Core 2 ONLY (skip if current SDK):
isAuthenticatedetsessionStatusne sont pas disponibles. Vérifiez!!userIdà la place.
Modèle Minimal
// Server Component
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
const { isAuthenticated, userId } = await auth() // MUST await!
if (!isAuthenticated) return <p>Not signed in</p>
return <p>Hello {userId}</p>
}
Core 2 ONLY (skip if current SDK):
isAuthenticatedn'est pas disponible. Utilisezif (!userId)à la place.
Rendu Conditionnel avec <Show>
Pour le rendu conditionnel côté client basé sur l'état d'authentification :
import { Show } from '@clerk/nextjs'
<Show when="signed-in" fallback={<p>Please sign in</p>}>
<Dashboard />
</Show>
Core 2 ONLY (skip if current SDK): Utilisez les composants
<SignedIn>et<SignedOut>à la place de<Show>. Voir la skillclerk-custom-ui,core-3/show-component.mdpour la table de migration complète.
Pièges Courants
| Symptôme | Cause | Solution |
|---|---|---|
undefined userId dans Server Component |
Missing await |
await auth() pas auth() |
| Auth ne fonctionne pas sur les routes API | Matcher manquant | Ajoutez '/(api|trpc)(.*)' à proxy.ts (Next.js <=15: middleware.ts) |
| Cache retourne les données d'un autre utilisateur | userId manquant dans la clé | Incluez userId dans la clé unstable_cache |
| Les mutations contournent l'auth | Server Action non protégée | Vérifiez auth() au début de l'action |
| Code d'erreur HTTP incorrect | Confusion 401/403 | 401 = non connecté, 403 = pas de permission |
Tokens de Session & JWTs Personnalisés
getToken() pour les APIs externes
Passez un JWT personnalisé aux services tiers (Hasura, Supabase, etc.) en utilisant les modèles JWT définis dans le dashboard Clerk.
Côté serveur (Server Component ou Route Handler) :
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
const { getToken } = await auth()
const token = await getToken({ template: 'hasura' })
if (!token) return <p>Not authenticated</p>
const res = await fetch('https://api.example.com/graphql', {
headers: { Authorization: `Bearer ${token}` },
})
const data = await res.json()
return <pre>{JSON.stringify(data)}</pre>
}
Côté client (Client Component) :
'use client'
import { useAuth } from '@clerk/nextjs'
export function DataFetcher() {
const { getToken } = useAuth()
async function fetchData() {
const token = await getToken({ template: 'supabase' })
if (!token) return
const res = await fetch('https://api.example.com/data', {
headers: { Authorization: `Bearer ${token}` },
})
return res.json()
}
return <button onClick={fetchData}>Fetch</button>
}
getToken() retourne null quand l'utilisateur n'est pas authentifié — vérifiez toujours avant utilisation.
useSession() pour les métadonnées de session
Accédez aux métadonnées de session dans les composants client :
'use client'
import { useSession } from '@clerk/nextjs'
export function SessionInfo() {
const { session } = useSession()
if (!session) return null
return (
<p>
Session {session.id} — last active: {session.lastActiveAt.toISOString()}
</p>
)
}
Vérification manuelle de JWT (sans middleware Clerk)
Pour les serveurs API autonomes qui reçoivent des tokens de session Clerk depuis le header Authorization ou le cookie __session (same-origin).
Utilisant verifyToken de @clerk/backend (recommandé) :
import { verifyToken } from '@clerk/backend'
const token = req.headers.authorization?.replace('Bearer ', '')
if (!token) return res.status(401).json({ error: 'No token' })
try {
const claims = await verifyToken(token, {
jwtKey: process.env.CLERK_JWT_KEY,
})
// claims.sub = userId
} catch {
return res.status(401).json({ error: 'Invalid token' })
}
Utilisant jsonwebtoken (quand vous ne pouvez pas utiliser @clerk/backend) :
import jwt from 'jsonwebtoken'
const publicKey = process.env.CLERK_PEM_PUBLIC_KEY!.replace(/\\n/g, '\n')
const token = req.headers.authorization?.replace('Bearer ', '')
if (!token) return res.status(401).json({ error: 'No token' })
try {
const claims = jwt.verify(token, publicKey, { algorithms: ['RS256'] }) as jwt.JwtPayload
// Vérifiez manuellement exp et nbf (jsonwebtoken fait cela automatiquement, mais vérifiez azp si nécessaire)
// claims.sub = userId
} catch {
return res.status(401).json({ error: 'Invalid or expired token' })
}
Sources de tokens :
- Requêtes same-origin : cookie
__session(Clerk le configure automatiquement) - Cross-origin / mobile / API-to-API : header
Authorization: Bearer <token>
CRITIQUE : Vérifiez toujours les claims
expetnbf.verifyTokendepuis@clerk/backendgère cela automatiquement ; avecjsonwebtokenbrut, définissezignoreExpiration: false(par défaut) et assurez-vous queclockToleranceest minimal.
Voir aussi
clerk-setupclerk-orgs