Next.js OAuth en pratique : intégrer Google, GitHub et WeChat pas à pas

La semaine dernière, sur un projet communautaire, le PM m’a lancé : « Ajoute une connexion Google, ça devrait être rapide. » Je me suis dit que la connexion tierce, j’en avais déjà lu — pas si compliqué. Résultat : une après-midi perdue, des erreurs redirect_uri, des échecs de token, et la console rouge qui défile. Le pire : j’avais suivi la doc officielle pas à pas, sans succès.
Le problème n’était pas le code, mais une compréhension trop superficielle d’OAuth. Authorization code, access token, callback — chaque terme seul, OK ; ensemble, le brouillard.
Cette fois, j’explique OAuth en langage clair — pas la RFC abstraite, mais l’analogie du retrait de colis. Vous comprendrez pourquoi il faut code et token, à quoi sert le callback, et où les configs piègent. Puis on configure trois connexions : Google (standard international), GitHub (dev-friendly), WeChat (indispensable en Chine, le plus pénible).
WeChat est la partie la plus casse-pieds : doc peu claire, qualification entreprise, debug local galère. Mais pour un projet domestic, on ne l’évite pas — je partage les pièges (tunnel, Provider custom). À la fin, une seule architecture couvre login domestic et international.
Comment fonctionne vraiment OAuth
Comprendre OAuth avec le retrait de colis
À mes débuts avec OAuth, authorization code et access token me donnaient mal à la tête. Puis j’ai compris : c’est exactement comme faire retirer un colis par un ami.
Imaginez : un colis vous attend au point relais (vos infos utilisateur), mais vous êtes au bureau. Votre ami (votre app Next.js) propose de le récupérer. Le relais ne remet pas un colis à n’importe qui — il faut prouver que vous autorisez cette personne :
1. Vous donnez un code de retrait à votre ami — c’est l’authorization code. Vous cliquez sur « Se connecter avec Google », Google affiche la page d’autorisation ; après consentement, un code temporaire revient dans l’URL de votre app.
2. Votre ami va au relais avec le code — votre backend échange le code contre un access token. Le relais vérifie aussi que cet ami est bien quelqu’un en qui vous avez confiance — vous avez enregistré son « numéro d’identité » (client_secret) à l’avance.
3. Après vérification, le colis est remis — code + identité OK → le relais donne le colis (infos utilisateur) à votre ami, qui vous le transmet. C’est l’appel API avec access_token.
Point clé : le code de retrait est à usage unique ; même intercepté, il est inutile sans le secret côté serveur. D’où le code en clair dans l’URL du navigateur, et le secret strictement backend.
Les quatre étapes en détail
Étape 1 : redirection vers le serveur OAuth
Clic sur « Se connecter avec Google » → redirection vers Google :
https://accounts.google.com/o/oauth2/v2/auth?
client_id=你的应用ID
&redirect_uri=http://localhost:3000/api/auth/callback/google
&response_type=code
&scope=email profile
Paramètres :
client_id: identifiant de votre app chez Googleredirect_uri: où renvoyer l’utilisateur après autorisationscope: quelles infos vous demandez
Étape 2 : consentement et réception du code
Après « Autoriser », Google redirige vers :
http://localhost:3000/api/auth/callback/google?code=4/0AfJohXl...&state=random123
Ce code est le code de retrait — courte durée de vie (5–10 min), usage unique.
Étape 3 : le backend échange le code contre access_token
Côté backend (pas frontend), avec code + client_secret :
const response = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
body: JSON.stringify({
code: '刚才拿到的code',
client_id: 'your_client_id',
client_secret: 'your_secret', // 这个绝不能暴露给前端
redirect_uri: 'http://localhost:3000/api/auth/callback/google',
grant_type: 'authorization_code'
})
})
const { access_token } = await response.json()
L’access_token ouvre l’accès aux infos utilisateur.
Étape 4 : récupérer le profil avec access_token
const userInfo = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
headers: {
Authorization: `Bearer ${access_token}`
}
})
const user = await userInfo.json()
// { email: "[email protected]", name: "Jean Dupont", picture: "URL avatar" }
Ensuite : créer ou mettre à jour l’utilisateur en base, générer la session — connexion terminée.
Tableau des concepts clés
| Terme | Explication | Où le voir |
|---|---|---|
| Client ID | Identifiant public de l’app | .env.local, paramètres URL |
| Client Secret | Mot de passe de l’app, strictement secret | Backend et variables d’environnement |
| Authorization Code | Code de retrait à usage unique | Paramètre code du callback |
| Access Token | Clé d’accès aux infos | Backend uniquement |
| Redirect URI | URL de retour après autorisation | Config OAuth, paramètre redirect_uri |
| Scope | Périmètre des permissions | Paramètre scope, ex. email profile |
| State | Chaîne aléatoire anti-CSRF | Paramètres authorize et callback |
Rôle du paramètre State : à l’initiation, générez une chaîne aléatoire (ex. abc123), stockez-la en session, transmettez-la au serveur OAuth. Au callback, vérifiez que le state reçu correspond — sinon, rejetez. NextAuth.js gère cela automatiquement.
Pourquoi ne pas renvoyer le token directement ?
Pourquoi un code intermédiaire plutôt qu’un access_token dans l’URL ?
Sécurité.
L’URL est visible (historique, logs, extensions). Un token en clair = clé des données utilisateur exposée.
Le code intercepté reste inutile car :
- Usage unique
- L’échange exige client_secret, connu du backend seul
- Le serveur OAuth vérifie aussi redirect_uri
Même avec le code, sans secret pas de token — les données restent protégées.
C’est l’Authorization Code Flow, le mode OAuth 2.0 le plus sûr pour une app web avec backend. L’Implicit Flow (token direct) est déconseillé.
Démarrer rapidement avec NextAuth.js
Pourquoi NextAuth.js
Plusieurs approches pour OAuth dans Next.js : tout écrire à la main ou utiliser une lib. J’ai tenté le DIY, pris trop de pièges, puis adopté NextAuth.js.
Raison 1 : recommandation officielle, écosystème mature
NextAuth.js est recommandé dans la doc Next.js, 70k+ stars, maintenance active. La v5 (nov. 2024) supporte App Router et Server Components.
Raison 2 : 30+ providers OAuth intégrés
Google, GitHub, Facebook, Twitter — quelques lignes de config. Pour WeChat (non intégré), un mécanisme de Provider custom évite de réimplémenter tout le flux.
Raison 3 : logique complexe automatisée
Sessions, signature JWT, stockage base, protection CSRF — automatiques. Vous vous concentrez sur le métier (email de bienvenue au premier login, etc.).
Structure du fichier de configuration
Avec App Router (Next.js 13+) :
app/api/auth/[...nextauth]/route.ts
Le catch-all [...nextauth] intercepte /api/auth/* :
/api/auth/signin— page de connexion/api/auth/callback/google— callback Google/api/auth/signout— déconnexion/api/auth/session— session courante
Configuration de base :
// app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google"
import GitHubProvider from "next-auth/providers/github"
export const authOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
GitHubProvider({
clientId: process.env.GITHUB_ID!,
clientSecret: process.env.GITHUB_SECRET!,
}),
],
// 可选:自定义登录页
pages: {
signIn: '/login',
},
// 可选:回调函数,处理登录后的逻辑
callbacks: {
async signIn({ user, account, profile }) {
// 可以在这里检查用户是否在白名单里
return true // 返回false会阻止登录
},
async session({ session, token }) {
// 给session添加额外信息
session.user.id = token.sub
return session
},
},
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
La ligne export { handler as GET, handler as POST } est indispensable sous App Router.
Convention de nommage des variables d’environnement
NextAuth.js est exigeant sur les noms, surtout en v5 :
Variables requises :
# .env.local
# NextAuth配置
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=your-secret-key-here
# 或者用新的命名(v5推荐)
AUTH_SECRET=your-secret-key-here
# Google OAuth
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
# 或者用AUTH_前缀(v5自动识别)
AUTH_GOOGLE_ID=your-google-client-id
AUTH_GOOGLE_SECRET=your-google-client-secret
# GitHub OAuth
GITHUB_ID=your-github-client-id
GITHUB_SECRET=your-github-client-secret
# 或者
AUTH_GITHUB_ID=your-github-client-id
AUTH_GITHUB_SECRET=your-github-client-secret
Points clés :
-
NEXTAUTH_URL : URL complète de l’app —
http://localhost:3000en dev, domaine réel avec https en prod. -
NEXTAUTH_SECRET / AUTH_SECRET : clé de signature JWT, chaîne aléatoire :
openssl rand -base64 32
Ne jamais exposer ni committer. En cas de fuite, régénérez — sinon session falsifiable.
- Préfixe AUTH_ : v5 reconnaît
AUTH_PROVIDER_IDetAUTH_PROVIDER_SECRETsansprocess.envexplicite dans le code.
Installation et config minimale
Étape 1 : installation
npm install next-auth
# 或
pnpm add next-auth
Étape 2 : créer la route API
Créez app/api/auth/[...nextauth]/route.ts avec le code ci-dessus.
Étape 3 : créer .env.local
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=运行 openssl rand -base64 32 生成的字符串
Étape 4 : bouton de connexion
// app/login/page.tsx
'use client'
import { signIn } from 'next-auth/react'
export default function LoginPage() {
return (
<div>
<button onClick={() => signIn('google')}>
Se connecter avec Google
</button>
<button onClick={() => signIn('github')}>
Se connecter avec GitHub
</button>
</div>
)
}
Étape 5 : envelopper avec SessionProvider
Pour useSession() côté client :
// app/layout.tsx
import { SessionProvider } from 'next-auth/react'
export default function RootLayout({ children }) {
return (
<html>
<body>
<SessionProvider>
{children}
</SessionProvider>
</body>
</html>
)
}
Le squelette est prêt. Le bouton plantera tant que les apps OAuth Google/GitHub ne sont pas configurées — c’est la suite.
Configuration Google en pratique
Google Cloud Console
Deux parties : créer l’app OAuth dans Google Cloud Console, puis brancher Next.js.
Étape 1 : ouvrir Google Cloud Console
https://console.cloud.google.com — connectez-vous. Premier usage : créez un projet, ex. « Mon blog ».
Étape 2 : activer Google+ API
Google+ est mort, mais OAuth s’appuie encore dessus. Menu « APIs & Services » → « Library », cherchez « Google+ API », « Enable ».
Étape 3 : créer les identifiants OAuth
- « Credentials » à gauche
- « Create Credentials » → « OAuth client ID »
- Première fois : « OAuth consent screen » — nom de l’app, email support, le reste peut attendre
- Application type : « Web application »
- Name : ex. « Next.js App »
Étape 4 : Redirect URIs (critique)
Authorized redirect URIs — deux entrées :
Développement :
http://localhost:3000/api/auth/callback/google
Production (après déploiement) :
https://yourdomain.com/api/auth/callback/google
Détails :
httpvshttps: http en local, https obligatoire en prod- Port : si vous tournez sur 3001, écrivez
localhost:3001 - Chemin :
/api/auth/callback/google— aucune faute - Pas de query string : arrêtez-vous à
/google, Google ajoute?code=xxx
« Create » → copiez Client ID et Client Secret.
Étape 5 : copier dans .env.local
GOOGLE_CLIENT_ID=你的Client ID.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxx
Intégration Next.js
GoogleProvider est déjà dans authOptions ; avec les bonnes variables, ça tourne. Optimisation possible :
// app/api/auth/[...nextauth]/route.ts
import GoogleProvider from "next-auth/providers/google"
export const authOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
authorization: {
params: {
prompt: "consent",
access_type: "offline",
response_type: "code"
}
}
}),
],
}
authorization.params :
prompt: "consent": écran d’autorisation à chaque login — pratique en test ; en prod, Google peut mémoriseraccess_type: "offline": refresh token pour accès long terme aux donnéesresponse_type: "code": Authorization Code Flow explicite
Tester le flux
npm run dev
http://localhost:3000/login → « Se connecter avec Google » → autorisation → retour app.
Récupérer la session côté serveur :
// app/page.tsx
import { getServerSession } from "next-auth"
import { authOptions } from "./api/auth/[...nextauth]/route"
export default async function Home() {
const session = await getServerSession(authOptions)
if (session) {
return <div>Bonjour, {session.user?.name}</div>
}
return <div>Non connecté</div>
}
Côté client :
'use client'
import { useSession } from "next-auth/react"
export default function Profile() {
const { data: session, status } = useSession()
if (status === "loading") return <div>Chargement...</div>
if (!session) return <div>Non connecté</div>
return (
<div>
<img src={session.user?.image} alt="Avatar" />
<p>{session.user?.name}</p>
<p>{session.user?.email}</p>
</div>
)
}
Dépannage des erreurs courantes
Erreur 1 : redirect_uri_mismatch
Error 400: redirect_uri_mismatch
The redirect URI in the request, http://localhost:3000/api/auth/callback/google,
does not match the ones authorized for the OAuth client.
L’URI configurée ne correspond pas au callback réel.
Étapes :
- DevTools → Network
- Clic connexion, inspectez l’URL Google
- Copiez la valeur de
redirect_uri - Collez-la telle quelle dans Authorized redirect URIs
- Vérifiez protocole, port, chemin, slashs
Erreur 2 : Access blocked: This app’s request is invalid
OAuth consent screen manquant ou utilisateurs test absents.
- Google Console → « OAuth consent screen »
- User Type : « External » ou « Internal »
- Renseignez les infos app
- External non publié : ajoutez votre email dans « Test users »
Erreur 3 : problème de port
App sur localhost:3001 mais URI en 3000 → erreur.
Solution : uniformiser le port 3000, ou ajouter plusieurs redirect URIs (3000, 3001, 3002).
Erreur 4 : exigence HTTPS
En prod sans https, Google refuse. Vercel, Netlify fournissent https automatiquement.
Configuration GitHub
GitHub OAuth App
Plus simple que Google — pas d’activation d’API.
Étape 1 : Developer settings
GitHub → avatar → Settings → Developer settings → OAuth Apps → New OAuth App.
Étape 2 : infos de l’app
- Application name : libre, invisible pour l’utilisateur
- Homepage URL :
http://localhost:3000en dev, votre domaine en prod - Authorization callback URL :
http://localhost:3000/api/auth/callback/github
GitHub est plus souple sur le callback qu’Google.
Register → Client ID. « Generate a new client secret » → Secret (affiché une fois).
Étape 3 : .env.local
GITHUB_ID=你的Client ID
GITHUB_SECRET=你的Client Secret
Intégration Next.js
import GitHubProvider from "next-auth/providers/github"
export const authOptions = {
providers: [
GitHubProvider({
clientId: process.env.GITHUB_ID!,
clientSecret: process.env.GITHUB_SECRET!,
}),
],
}
Rien d’autre à configurer.
GitHub vs Google
| Critère | GitHub | |
|---|---|---|
| Difficulté | Moyenne, API à activer | Simple, création directe |
| Redirect URI | Strict, correspondance exacte | Plus souple |
| HTTPS | Obligatoire en prod | http OK sur localhost |
| Scope | À spécifier | Souvent suffisant par défaut |
| Infos user | email, name, picture | login, email, avatar_url |
Attention : l’email GitHub peut être null si l’utilisateur masque son adresse :
const userEmail = session.user?.email || 'Email non fourni'
Connexion WeChat (contexte Chine)
Trois modes de connexion WeChat
| Mode | Cas d’usage | Exigences | UX |
|---|---|---|---|
| Open Platform — site web | Site indépendant | Entreprise, domaine enregistré, HTTPS | QR code, PC |
| Autorisation page publique | H5 dans WeChat | Compte officiel certifié | Navigateur WeChat uniquement |
| WeChat Work | Intranet entreprise | Compte WeChat Work | Employés uniquement |
Ici : Open Platform site web — adapté à un site Next.js standalone.
Open Platform WeChat (barrière élevée)
Prérequis :
- Licence entreprise (pas les particuliers)
- Domaine enregistré (ICP)
- Certificat HTTPS
Étape 1 : compte développeur
https://open.weixin.qq.com → « S’inscrire » → « Développeur application web » → licence → validation (1–2 jours ouvrés).
Étape 2 : créer l’application web
Centre de gestion → Application web → créer :
- Nom, description
- Site officiel : domaine enregistré
- Domaine de callback : domaine seul, sans protocole ni chemin, ex.
yourdomain.com
Différence avec Google/GitHub : WeChat veut le domaine, pas l’URL complète. Tous les chemins sous ce domaine sont acceptés.
Validation 1–7 jours → AppID et AppSecret.
Étape 3 : variables
WECHAT_APP_ID=你的AppID
WECHAT_APP_SECRET=你的AppSecret
Provider custom NextAuth.js
WeChat n’est pas intégré — Provider custom :
// app/api/auth/[...nextauth]/route.ts
const WeChatProvider = {
id: "wechat",
name: "WeChat",
type: "oauth",
authorization: {
url: "https://open.weixin.qq.com/connect/qrconnect",
params: {
appid: process.env.WECHAT_APP_ID,
scope: "snsapi_login",
response_type: "code",
},
},
token: {
url: "https://api.weixin.qq.com/sns/oauth2/access_token",
async request({ params, provider }) {
const response = await fetch(
`https://api.weixin.qq.com/sns/oauth2/access_token?appid=${process.env.WECHAT_APP_ID}&secret=${process.env.WECHAT_APP_SECRET}&code=${params.code}&grant_type=authorization_code`
)
const tokens = await response.json()
return { tokens }
},
},
userinfo: {
url: "https://api.weixin.qq.com/sns/userinfo",
async request({ tokens }) {
const response = await fetch(
`https://api.weixin.qq.com/sns/userinfo?access_token=${tokens.access_token}&openid=${tokens.openid}`
)
return await response.json()
},
},
profile(profile) {
return {
id: profile.unionid || profile.openid,
name: profile.nickname,
email: null, // 微信不提供邮箱
image: profile.headimgurl,
}
},
}
export const authOptions = {
providers: [
WeChatProvider,
// ...其他providers
],
}
Debug en développement
WeChat exige HTTPS et domaine enregistré — le local est pénible. Deux approches :
Option 1 : tunnel (recommandé)
ngrok ou cpolar pour exposer le port 3000 :
# 使用ngrok
ngrok http 3000
# 或使用cpolar(国内更稳定)
cpolar http 3000
Domaine temporaire ex. https://abc123.ngrok.io → configurez-le comme domaine de callback WeChat.
Option 2 : compte de test
Compte sandbox sans qualification entreprise :
- https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
- AppID/Secret de test après scan QR
- Callback via domaine tunnel
Limité : vous seul pouvez tester ; les autres voient « compte non suivi ».
Spécificités WeChat
Différence 1 : openid et unionid
openid: identifiant unique dans l’app couranteunionid: identifiant unique sous le même compte Open Platform (plusieurs apps liées)
Préférez unionid ; sinon openid.
Différence 2 : pas d’email
WeChat ne renvoie pas d’email — email: null. Demandez un email complémentaire si nécessaire.
Différence 3 : access_token court
Google/GitHub ~1 h ; WeChat ~2 h, refresh limité (~10/jour). Gérez le renouvellement proprement.
Synthèse
Du principe OAuth à la config sur trois plateformes — parcours complet de la connexion tierce.
Points clés :
- Code + token en deux temps = sécurité ; code en clair OK, secret backend obligatoire
- NextAuth.js : sessions, CSRF, etc. — vous codez le métier
- Google strict sur redirect URI ; GitHub le plus simple ; WeChat le plus exigeant mais indispensable en Chine
- WeChat : entreprise + domaine enregistré ; tunnel + compte test en dev
Astuces :
openssl rand -base64 32pour NEXTAUTH_SECRET- Plusieurs ports dans Google Console
- Email GitHub nullable — gérez le cas
- unionid > openid pour identifiant cross-app
Le plus dur n’est pas le code — c’est le modèle mental OAuth et les différences de config par plateforme. Si cet article vous évite quelques pièges, mission accomplie.
La prochaine fois qu’on vous demande « ajoute Google login », ce ne sera plus une après-midi perdue.
Configuration complète OAuth Next.js
De la compréhension d'OAuth à la configuration Google, GitHub et WeChat
⏱️ Estimated time: 2 hr
- 1
Step 1: Comprendre OAuth (analogie du colis)
Idée centrale OAuth : ne pas donner votre mot de passe à une app tierce — autoriser un laissez-passer temporaire chez le provider.
Analogie colis :
• Vous (utilisateur) → personne qui veut se connecter
• Ami (app Next.js) → celui qui retire le colis
• Point relais (provider OAuth) → Google, GitHub, WeChat
• Badge permanent (mot de passe) → ne se partage pas
• Laissez-passer temporaire (access_token) → limité dans le temps et en permissions
Quatre étapes :
1. Vous donnez le code de retrait (authorization code)
2. L'ami va au relais avec code + pièce d'identité (code + client_secret → access_token)
3. Le relais vérifie et remet le colis (infos utilisateur)
4. L'ami vous le transmet (connexion réussie)
Points clés :
• Le code est à usage unique, courte durée (~10 min)
• client_secret strictement serveur
• access_token limité en durée et en scope - 2
Step 2: Configurer Google
1. Créer un client OAuth dans Google Cloud Console :
• https://console.cloud.google.com
• Projet → API et services → Identifiants → ID client OAuth
• Type : application Web
• URI de redirection : http://localhost:3000/api/auth/callback/google
2. Récupérer client_id et client_secret
3. Configurer NextAuth.js :
```ts
// app/api/auth/[...nextauth]/route.ts
import NextAuth from 'next-auth'
import GoogleProvider from 'next-auth/providers/google'
export const authOptions = {
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
})
],
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
```
4. Variables d'environnement :
```
GOOGLE_CLIENT_ID=votre_client_id
GOOGLE_CLIENT_SECRET=votre_client_secret
NEXTAUTH_URL=http://localhost:3000
NEXTAUTH_SECRET=chaîne_aléatoire
```
5. Dans la page :
```tsx
import { signIn } from 'next-auth/react'
<button onClick={() => signIn('google')}>
Se connecter avec Google
</button>
``` - 3
Step 3: Configurer GitHub
1. Créer une OAuth App GitHub :
• https://github.com/settings/developers
• New OAuth App
• Authorization callback URL : http://localhost:3000/api/auth/callback/github
2. Récupérer Client ID et Client Secret
3. NextAuth.js :
```ts
import GitHubProvider from 'next-auth/providers/github'
providers: [
GitHubProvider({
clientId: process.env.GITHUB_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
})
]
```
4. Variables :
```
GITHUB_CLIENT_ID=votre_client_id
GITHUB_CLIENT_SECRET=votre_client_secret
```
Même logique que Google, provider différent. - 4
Step 4: Configurer WeChat (cas particulier)
1. Enregistrer l'app sur WeChat Open Platform :
• https://open.weixin.qq.com
• Créer application web
• AppID et AppSecret
• Qualification entreprise requise
2. Domaine de callback :
• Format : yourdomain.com (sans http:// ni https://)
• Domaine enregistré ICP
3. Provider custom :
```ts
import WeChatProvider from 'next-auth/providers/wechat'
providers: [
WeChatProvider({
clientId: process.env.WECHAT_CLIENT_ID!,
clientSecret: process.env.WECHAT_CLIENT_SECRET!,
})
]
```
4. Debug local via tunnel :
• ngrok ou frp
• Callback = adresse tunnel
• En prod : adresse réelle
Points clés :
• Qualification entreprise
• Tunnel en local
• unionid préférable à openid - 5
Step 5: Résoudre les erreurs courantes
Erreur 1 : redirect_uri_mismatch
• Cause : URI callback incorrecte
• Solution : configurer redirect_uri chez le provider
• Local et prod doivent tous deux être déclarés
Erreur 2 : variables d'environnement manquantes
• Vérifier .env.local
• Noms de variables corrects
• Variables aussi sur Vercel Dashboard
Erreur 3 : OK en local, KO en prod
• URI callback différente
• Ajouter https://yourdomain.com/api/auth/callback/google
Sécurité :
• client_secret côté serveur uniquement
• Paramètre state anti-CSRF
• Vérifier state au callback
FAQ
Comment fonctionne OAuth ?
Scénario : un colis (vos infos) vous attend au relais, vous êtes au bureau. Votre ami (app Next.js) propose de le récupérer.
Flux :
1. Vous donnez un code de retrait (authorization code)
• Clic « Se connecter avec Google » → page d'autorisation Google
• Après consentement, code temporaire dans l'URL
2. L'ami va au relais (code + client_secret → access_token)
• Le backend échange code + secret chez Google
• Google vérifie que l'app est de confiance (client_secret)
3. Vérification OK → colis remis (infos utilisateur)
• Google confirme → profil transmis → connexion réussie
Points clés :
• Code à usage unique, ~10 minutes
• client_secret serveur uniquement
• access_token limité en durée et permissions
Avantage : pas besoin de donner votre mot de passe à l'app tierce.
Qu'est-ce que redirect_uri_mismatch ?
Le provider OAuth vérifie l'adresse de retour — incohérence = cette erreur.
Solution :
1. Configurer redirect_uri chez le provider
2. Local : http://localhost:3000/api/auth/callback/google
3. Prod : https://yourdomain.com/api/auth/callback/google
4. Les deux environnements doivent être déclarés
Erreurs fréquentes :
• Local seulement, pas la prod
• Slash en trop ou manquant
• http vs https
Vérification :
• Chemin NextAuth par défaut : /api/auth/callback/[provider]
• Correspondance exacte avec la config provider
La propagation peut prendre quelques minutes.
Pourquoi WeChat est-il si pénible ?
1. Qualification entreprise
• Particuliers exclus
• Licence et documents
• Validation 1–3 jours ouvrés
2. Documentation
• Peu claire
• Messages d'erreur vagues
• Debug difficile
3. Debug local
• Tunnel obligatoire (ngrok, frp)
• Callback complexe
• Limites environnement test
4. Configuration
• Provider custom
• openid vs unionid
• Domaine callback avec enregistrement ICP
Solutions :
• Tunnel pour le dev
• Provider custom
• unionid pour identifiant unique
• Patience pour la validation
Conseil : priorisez Google ou GitHub ; WeChat en complément si nécessaire.
Comment configurer un Provider custom ?
```ts
import type { OAuthConfig, OAuthUserConfig } from 'next-auth/providers'
function WeChatProvider(options: OAuthUserConfig<WeChatProfile>): OAuthConfig<WeChatProfile> {
return {
id: 'wechat',
name: 'WeChat',
type: 'oauth',
authorization: {
url: 'https://open.weixin.qq.com/connect/qrconnect',
params: {
appid: options.clientId,
redirect_uri: options.callbackUrl,
response_type: 'code',
scope: 'snsapi_login',
state: 'state',
},
},
token: {
url: 'https://api.weixin.qq.com/sns/oauth2/access_token',
},
userinfo: {
url: 'https://api.weixin.qq.com/sns/userinfo',
},
profile(profile) {
return {
id: profile.openid,
name: profile.nickname,
email: null,
image: profile.headimgurl,
}
},
...options,
}
}
```
Points clés :
• URL authorization, token, userinfo
• Fonction profile
WeChat est complexe — référez-vous à la doc officielle ou un Provider existant.
Différence entre unionid et openid ?
• Identifiant unique dans l'app courante
• Différent par application
• Adapté à une seule app
unionid :
• Identifiant unique sous WeChat Open Platform
• Identique pour le même utilisateur sur plusieurs apps
• Adapté au multi-app
Conseil :
• Une app → openid
• Plusieurs apps → unionid
Exemple :
```ts
const response = await fetch(
`https://api.weixin.qq.com/sns/userinfo?access_token=${accessToken}&openid=${openid}`
)
const data = await response.json()
const unionid = data.unionid
```
unionid est préférable comme identifiant stable ; autorisation et Open Platform requis.
Comment déboguer WeChat en local ?
Solution : tunnel
1. ngrok :
```bash
ngrok http 3000
```
2. Adresse publique :
```
https://xxxxx.ngrok.io
```
3. Configuration :
• Open Platform : https://xxxxx.ngrok.io/api/auth/callback/wechat
• .env.local : NEXTAUTH_URL=https://xxxxx.ngrok.io
4. Test :
• Ouvrir https://xxxxx.ngrok.io
• Connexion WeChat
Notes :
• ngrok gratuit change d'URL à chaque redémarrage
• Pas de ngrok en prod
• Après tests : adresse de production
Alternative : frp auto-hébergé, URL plus stable.
13 min de lecture · Publié le: 19 déc. 2025 · Mis à jour le: 27 juil. 2026
Guide complet Next.js
Si vous arrivez depuis la recherche, le plus rapide est de passer à l’article précédent ou suivant de cette série.
Précédent
Guide complet OAuth Next.js : Google, GitHub, WeChat — configuration et bonnes pratiques
Comprenez OAuth 2.0 simplement et configurez pas à pas Google, GitHub et WeChat dans Next.js. Résolvez redirect_uri_mismatch, failles de sécurité et autres pièges courants.
Partie 13 sur 51
Suivant
Guide complet de l'internationalisation Next.js : bonnes pratiques avec next-intl
Plongée dans l'i18n avec Next.js App Router : configuration complète de next-intl, routage multilingue, gestion des fichiers de traduction et exemples de code prêts pour la production.
Partie 15 sur 51



Commentaires
Connectez-vous avec GitHub pour laisser un commentaire