Changer le thème

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

Easton editorial illustration: monorepo project desk

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 Google
  • redirect_uri : où renvoyer l’utilisateur après autorisation
  • scope : 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

TermeExplicationOù le voir
Client IDIdentifiant public de l’app.env.local, paramètres URL
Client SecretMot de passe de l’app, strictement secretBackend et variables d’environnement
Authorization CodeCode de retrait à usage uniqueParamètre code du callback
Access TokenClé d’accès aux infosBackend uniquement
Redirect URIURL de retour après autorisationConfig OAuth, paramètre redirect_uri
ScopePérimètre des permissionsParamètre scope, ex. email profile
StateChaîne aléatoire anti-CSRFParamè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 :

  1. Usage unique
  2. L’échange exige client_secret, connu du backend seul
  3. 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 :

  1. NEXTAUTH_URL : URL complète de l’app — http://localhost:3000 en dev, domaine réel avec https en prod.

  2. 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.

  1. Préfixe AUTH_ : v5 reconnaît AUTH_PROVIDER_ID et AUTH_PROVIDER_SECRET sans process.env explicite 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 :

  • http vs https : 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émoriser
  • access_type: "offline" : refresh token pour accès long terme aux données
  • response_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 :

  1. DevTools → Network
  2. Clic connexion, inspectez l’URL Google
  3. Copiez la valeur de redirect_uri
  4. Collez-la telle quelle dans Authorized redirect URIs
  5. 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:3000 en 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èreGoogleGitHub
DifficultéMoyenne, API à activerSimple, création directe
Redirect URIStrict, correspondance exactePlus souple
HTTPSObligatoire en prodhttp OK sur localhost
ScopeÀ spécifierSouvent suffisant par défaut
Infos useremail, name, picturelogin, 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

ModeCas d’usageExigencesUX
Open Platform — site webSite indépendantEntreprise, domaine enregistré, HTTPSQR code, PC
Autorisation page publiqueH5 dans WeChatCompte officiel certifiéNavigateur WeChat uniquement
WeChat WorkIntranet entrepriseCompte WeChat WorkEmployé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 :

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 courante
  • unionid : 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 32 pour 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. 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. 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. 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. 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. 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 ?
Analogie du retrait de colis :

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 ?
Cause : l'URI de callback ne correspond pas à la configuration.

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 ?
Problèmes :

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 ?
WeChat nécessite 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 ?
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 ?
Problème : WeChat exige un domaine de callback — localhost impossible.

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

Commentaires

Connectez-vous avec GitHub pour laisser un commentaire

Easton BlogEaston Blog