Guía completa de OAuth en Next.js: Google, GitHub, WeChat y mejores prácticas

Haces clic en «Iniciar sesión con Google», saltas a Google, autorizas, vuelves y ya estás dentro.
Lo has hecho mil veces. Pero cuando quieres añadir login de terceros a tu proyecto, de repente todo se complica: ¿por qué hay dos redirecciones? ¿Qué es una URL de callback? ¿Qué demonios es redirect_uri_mismatch? ¿Por qué en local va bien y en producción falla?
La primera vez que configuré OAuth leí montones de documentación llena de «código de autorización», access_token y client_secret, y cuanto más leía, peor. Al final tardé dos días y un montón de errores en entenderlo.
En este artículo quiero explicar OAuth con las palabras más directas posibles. Sin amontonar términos ni teoría vacía: cómo funciona de verdad y cómo configurar Google, GitHub y WeChat en Next.js. Cuando lo veas claro, verás que tampoco es tan misterioso.
¿Qué es OAuth 2.0? (Explicado con un ejemplo cotidiano)
Primero, una analogía sencilla
Imagina que vives en una urbanización con portal. Un día compras algo online y quieres que el repartidor lo deje en tu puerta. Problema: hay control de acceso y el repartidor no puede entrar.
¿La forma clásica? Darle tu tarjeta del portal. Pero es arriesgado: si se queda con ella, podría entrar cuando quiera.
La forma más inteligente: vas con el vigilante y dices «tengo un paquete». El vigilante le da al repartidor un pase temporal que dice «solo puede entrar hoy de 14:00 a 16:00, solo al edificio A». Cuando entrega el paquete, el pase caduca.
Esa es la idea central de OAuth.
En esta analogía:
- Tú = el usuario (quien quiere iniciar sesión)
- El repartidor = la app de terceros (tu web)
- El vigilante = el proveedor OAuth (Google, WeChat, GitHub, etc.)
- La tarjeta del portal = tu contraseña (no se la das a nadie)
- El pase temporal = access_token (con caducidad y permisos limitados)
No entregas tu contraseña a la app de terceros; solo autorizas que vaya al proveedor OAuth a pedir un «pase temporal».
El flujo OAuth en cinco pasos (modo código de autorización)
Ahora veamos cómo encaja esto en el login OAuth de Next.js.
Paso 1: el usuario hace clic en «Iniciar sesión con Google» en tu web.
Paso 2: tu web redirige al usuario a la página de autorización de Google, con una URL parecida a esta:
https://accounts.google.com/o/oauth2/auth?
client_id=TuAppID
&redirect_uri=http://localhost:3000/api/auth/callback/google
&response_type=code
&scope=openid email profile
&state=CadenaAleatoria
Aquí tu web le dice a Google: «Soy la app X (client_id), el usuario quiere entrar con vuestra cuenta; pídele confirmación y, cuando termine, devuélvelo a esta dirección (redirect_uri).»
Paso 3: en Google el usuario ve «La app X quiere acceder a tu información básica» y pulsa «Permitir».
Paso 4: Google redirige de vuelta a tu web (redirect_uri) con un código de autorización (code) en la URL:
http://localhost:3000/api/auth/callback/google?code=ABCD1234&state=CadenaAleatoria
Ojo: ese code es solo un comprobante, no el pase final. Caduca pronto (suele durar unos 10 minutos) y solo sirve una vez.
Paso 5: el backend de tu web lleva ese code, junto con tu client_secret, a Google para cambiarlo por el access_token real:
// Código de backend (simplificado)
const response = await fetch('https://oauth2.googleapis.com/token', {
method: 'POST',
body: JSON.stringify({
code: 'ABCD1234',
client_id: 'TuAppID',
client_secret: 'TuAppPassword',
redirect_uri: 'http://localhost:3000/api/auth/callback/google',
grant_type: 'authorization_code',
}),
})
const { access_token } = await response.json()
Con el access_token, tu web puede pedir a Google el email, avatar, nombre, etc.
Paso 6 (opcional): usar access_token para obtener datos del usuario:
const userInfo = await fetch('https://www.googleapis.com/oauth2/v2/userinfo', {
headers: {
Authorization: `Bearer ${access_token}`,
},
})
Al terminar el flujo, tu web ya sabe «quién es este usuario» y puede crear una sesión para mantenerlo conectado.
Conceptos clave en lenguaje llano
Si aún te suenan raros algunos términos, aquí van en plan sencillo:
-
client_id: el «DNI» de tu app en Google. Puede ser público; no pasa nada si alguien lo ve.
-
client_secret: la «contraseña» de tu app. Nunca debe filtrarse; solo se usa en el backend. Si alguien lo obtiene, puede hacerse pasar por tu app y acceder a datos de usuarios.
-
redirect_uri: la dirección a la que Google devuelve al usuario tras autorizar. Debe estar registrada de antemano en Google Cloud Console. Google la valida al milímetro; hasta una barra de más provoca redirect_uri_mismatch.
-
state: una cadena aleatoria contra ataques CSRF. La generas al iniciar la autorización y Google la devuelve igual. Comprueba que la que vuelve es la misma; si no, la petición puede ser falsa.
-
code: código de autorización temporal. Caduca en unos 10 minutos y solo vale una vez. Sirve para demostrar que el usuario ya autorizó en Google.
-
access_token: el «pase» de verdad. Con él tu web puede obtener información del usuario en Google en su nombre. También caduca, normalmente entre 1 hora y varios días.
¿Por qué code y access_token en dos pasos?
Podrías preguntarte: ¿por qué no devolver directamente el access_token?
Por seguridad. El code viaja en la redirección del navegador (visible en el frontend); el access_token se intercambia servidor a servidor (invisible para el frontend). Si el access_token fuera en la URL, el historial del navegador, logs o monitorización de red podrían filtrarlo. Cambiar code por token exige client_secret, que solo vive en el backend.
Next.js + NextAuth.js: configurar Google (la puerta de entrada más fácil)
¿Por qué NextAuth.js?
Implementar OAuth a mano es pesado: callbacks, sesiones, CSRF, almacenamiento de tokens… muchos detalles.
La buena noticia es NextAuth.js (ahora Auth.js v5). Tiene más de 15k estrellas en GitHub, comunidad activa y soporta más de 50 proveedores OAuth (Google, GitHub, WeChat, Twitter, etc.) casi listos. La versión actual encaja con App Router de Next.js 14+ y es más sencilla que antes.
En la práctica, NextAuth.js te ahorra el 80 % del trabajo repetitivo.
Paso 1: crear la app en Google Cloud
Antes de escribir código, registra tu app en Google y obtén client_id y client_secret.
-
Abre Google Cloud Console e inicia sesión con tu cuenta de Google.
-
Si es la primera vez, crea un proyecto. El nombre da igual, por ejemplo «My Next.js App».
-
En el menú lateral: «APIs y servicios» → «Credenciales».
-
Pulsa «Crear credenciales» → «ID de cliente de OAuth».
-
Si es la primera vez, puede pedirte configurar la «Pantalla de consentimiento de OAuth». Pon nombre de la app y email de soporte; el resto puede esperar (tipo de usuario «Externo»; en pruebas no hace falta revisión).
-
Vuelve a crear el ID de cliente OAuth y elige tipo «Aplicación web».
-
Aquí está lo importante: en «URIs de redirección autorizados» añade:
- Desarrollo local:
http://localhost:3000/api/auth/callback/google - Producción (cuando despliegues):
https://yourdomain.com/api/auth/callback/google
Debe coincidir exactamente con lo que uses en código. Una barra de más o de menos y tendrás redirect_uri_mismatch. Yo caí en eso al principio.
- Desarrollo local:
-
Pulsa «Crear»; aparecerán Client ID y Client Secret. Cópialos; los usarás enseguida.
Paso 2: instalar NextAuth.js y variables de entorno
En tu proyecto Next.js:
npm install next-auth@beta
Instala la versión @beta (v5, la más reciente).
Crea .env.local en la raíz y añade Client ID y Secret:
GOOGLE_CLIENT_ID=TuClient_ID.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=TuClient_Secret
NEXTAUTH_SECRET=GeneraUnaCadenaAleatoria
NEXTAUTH_URL=http://localhost:3000
Genera NEXTAUTH_SECRET con:
openssl rand -base64 32
Al desplegar en producción, cambia NEXTAUTH_URL por tu dominio.
Paso 3: archivo de configuración de NextAuth
Crea app/api/auth/[...nextauth]/route.ts (con Pages Router sería pages/api/auth/[...nextauth].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!,
}),
],
callbacks: {
async signIn({ user, account, profile }) {
// Callback al iniciar sesión; aquí puedes guardar al usuario en la base de datos
console.log("Usuario conectado:", user)
return true // true = permitir el login
},
async session({ session, token }) {
// Personalizar el contenido de la sesión
if (session.user) {
session.user.id = token.sub // añadir user id a la sesión
}
return session
},
},
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
NextAuth.js se encarga de todo el flujo OAuth. La ruta /api/auth/callback/google se genera sola; no hace falta escribirla.
Paso 4: botón de inicio de sesión
En cualquier componente:
'use client' // App Router: componente cliente
import { signIn, signOut, useSession } from "next-auth/react"
export default function LoginButton() {
const { data: session } = useSession()
if (session) {
// Usuario conectado
return (
<div>
<p>Bienvenido, {session.user?.name}</p>
<img src={session.user?.image || ''} alt="Avatar" />
<button onClick={() => signOut()}>Cerrar sesión</button>
</div>
)
}
// Usuario no conectado
return <button onClick={() => signIn('google')}>Iniciar sesión con Google</button>
}
signIn('google') redirige a Google; tras autorizar vuelve y el usuario queda conectado. Muy simple.
Paso 5: envolver el layout raíz con SessionProvider
Para que useSession funcione en toda la app, envuelve con el Provider:
// app/layout.tsx
import { SessionProvider } from "next-auth/react"
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html>
<body>
<SessionProvider>{children}</SessionProvider>
</body>
</html>
)
}
Listo: ya tienes una app Next.js con login de Google.
Problemas habituales
Problema 1: redirect_uri_mismatch
Es el error más común; me pasó la primera vez.
El mensaje suele ser: Error 400: redirect_uri_mismatch
Causa: la URL de callback en Google Cloud Console no coincide con la petición real.
Solución:
- Comprueba que «URIs de redirección autorizados» sea
http://localhost:3000/api/auth/callback/google(sin barras de más) - Comprueba que
NEXTAUTH_URLen.env.localseahttp://localhost:3000 - Si cambiaste el puerto (por ejemplo 3001), actualiza ambos sitios
Problema 2: en local va bien, desplegado falla
También me pasó: en local perfecto, en Vercel el botón no hace nada o da error.
Causa: olvidaste actualizar variables de entorno de producción.
Solución:
- En Google Cloud Console añade el dominio de producción:
https://yourdomain.com/api/auth/callback/google - En Vercel (o tu plataforma) cambia
NEXTAUTH_URLahttps://yourdomain.com - Vuelve a desplegar
Problema 3: session es null tras el login
Si useSession() devuelve siempre null, revisa si olvidaste <SessionProvider> en el layout raíz.
Problema 4: TypeError: Cannot read property ‘user’ of null
Suele ocurrir cuando accedes a session.user mientras la sesión aún carga.
Solución: comprueba antes si existe:
const { data: session, status } = useSession()
if (status === 'loading') {
return <div>Cargando...</div>
}
if (!session) {
return <div>No has iniciado sesión</div>
}
// Aquí ya puedes usar session.user con seguridad
Configurar GitHub (entender las diferencias)
Con Google ya montado, GitHub es más sencillo. Aun así hay matices respecto a Google.
Diferencias entre OAuth de GitHub y Google
Lo similar: ambos usan el modo código de autorización de OAuth 2.0; el flujo es el mismo.
Lo distinto:
- Permisos más granulares: el scope de GitHub es más complejo. Por defecto solo obtienes información pública; para el email (sobre todo privado) hace falta
user:email. - Callback más flexible: Google exige la URL completa; GitHub suele bastar con el dominio.
- Tipo de app: GitHub admite OAuth App de cuenta personal u organización.
Paso 1: crear OAuth App en GitHub
-
Inicia sesión en GitHub → avatar → Settings → «Developer settings» en el menú lateral.
-
«OAuth Apps» → «New OAuth App».
-
Rellena:
- Application name: nombre de tu app (lo verá el usuario al autorizar)
- Homepage URL: home de tu web, por ejemplo
http://localhost:3000 - Authorization callback URL:
http://localhost:3000/api/auth/callback/github
-
«Register application», luego «Generate a new client secret»; copia Client ID y Client Secret.
Paso 2: variables de entorno
En .env.local:
GITHUB_CLIENT_ID=TuGitHub_Client_ID
GITHUB_CLIENT_SECRET=TuGitHub_Client_Secret
Paso 3: actualizar NextAuth
En el mismo route.ts, añade GitHubProvider:
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_CLIENT_ID!,
clientSecret: process.env.GITHUB_CLIENT_SECRET!,
// Para email privado, añade esto
authorization: {
params: {
scope: 'read:user user:email'
}
}
}),
],
callbacks: {
// ... callbacks anteriores
},
}
const handler = NextAuth(authOptions)
export { handler as GET, handler as POST }
Paso 4: actualizar el botón de login
return (
<div>
<button onClick={() => signIn('google')}>Iniciar sesión con Google</button>
<button onClick={() => signIn('github')}>Iniciar sesión con GitHub</button>
</div>
)
¡Hecho!
Sobre scope (alcance de permisos)
El scope de GitHub define qué datos puedes leer. Los habituales:
read:user: información pública y privada (nombre, avatar, bio, etc.)user:email: correo del usuario (también privado)public_repo: repos públicos del usuariorepo: todos los repos (públicos y privados; permiso fuerte, úsalo con cuidado)
Para login basta read:user user:email.
Sin user:email, NextAuth.js solo obtiene el email público. Si el usuario lo ocultó en GitHub, session.user.email será null. A mí me confundió un rato; pensé que era un bug de código.
Un detalle: el usuario de GitHub puede no tener email público
A diferencia de Google (email obligatorio), en GitHub el email puede ser privado. Si tu app lo necesita (notificaciones, etc.), compruébalo en el callback signIn:
async signIn({ user, account }) {
if (account?.provider === 'github' && !user.email) {
// Sin email: rechazar login o pedir al usuario que lo complete
console.log("Usuario de GitHub sin email")
return false // rechazar login
}
return true
}
Configurar WeChat (el caso especial en China)
WeChat es más complejo que Google y GitHub, sobre todo porque su ecosistema no es el mismo que el internacional.
¿Por qué WeChat es distinto?
Puntos clave:
- Requiere escanear QR: en web de PC el usuario saca el móvil y escanea (no basta con pulsar en la página como en Google/GitHub).
- Sin provider oficial en NextAuth.js: hay que escribir uno personalizado.
- Restricciones de callback: el dominio debe estar registrado (ICP); localhost no vale; depurar en local es incómodo.
- openid y unionid: el mismo usuario tiene openid distinto en cada app; para unificar usuarios entre apps hace falta unionid.
Paso 1: registro en WeChat Open Platform
-
Abre WeChat Open Platform y regístrate.
-
Crea una «aplicación web» (no cuenta oficial ni mini programa).
-
Rellena datos, sube capturas y espera revisión (1-3 días laborables).
-
Tras aprobar, obtienes AppID y AppSecret (equivalentes a client_id y client_secret).
-
En «Información de desarrollo» configura el dominio de callback (solo dominio, sin ruta completa, p. ej.
yourdomain.com).
Paso 2: provider personalizado de WeChat
Como NextAuth.js no trae WeChat, créalo en lib/wechat-provider.ts:
import type { OAuthConfig, OAuthUserConfig } from "next-auth/providers"
export interface WeChatProfile {
openid: string
nickname: string
headimgurl: string
sex: number
province: string
city: string
country: string
unionid?: string
}
export default function WeChatProvider<P extends WeChatProfile>(
options: OAuthUserConfig<P>
): OAuthConfig<P> {
return {
id: "wechat",
name: "WeChat",
type: "oauth",
// URL de autorización WeChat (apps web de PC)
authorization: {
url: "https://open.weixin.qq.com/connect/qrconnect",
params: {
scope: "snsapi_login",
appid: options.clientId,
response_type: "code",
},
},
// Intercambiar code por access_token
token: {
url: "https://api.weixin.qq.com/sns/oauth2/access_token",
params: {
appid: options.clientId,
secret: options.clientSecret,
grant_type: "authorization_code",
},
},
// Obtener datos del usuario
userinfo: {
url: "https://api.weixin.qq.com/sns/userinfo",
async request({ tokens, provider }) {
const res = await fetch(
`${provider.userinfo?.url}?access_token=${tokens.access_token}&openid=${tokens.openid}&lang=zh_CN`
)
return await res.json()
},
},
// Convertir perfil WeChat al formato NextAuth
profile(profile) {
return {
id: profile.openid,
name: profile.nickname,
email: null, // WeChat no proporciona email
image: profile.headimgurl,
}
},
options,
}
}
Paso 3: variables de entorno
En .env.local:
WECHAT_CLIENT_ID=TuWeChatAppID
WECHAT_CLIENT_SECRET=TuWeChatAppSecret
Paso 4: usarlo en NextAuth
Actualiza route.ts:
import WeChatProvider from "@/lib/wechat-provider"
export const authOptions = {
providers: [
GoogleProvider({...}),
GitHubProvider({...}),
WeChatProvider({
clientId: process.env.WECHAT_CLIENT_ID!,
clientSecret: process.env.WECHAT_CLIENT_SECRET!,
}),
],
}
Paso 5: ¿cómo probar en local?
WeChat no admite localhost como dominio de callback; no puedes probar directo en local.
Dos opciones:
Opción 1: túnel (ngrok, cpolar)
Expón tu servicio local a internet con ngrok o cpolar:
# Instalar ngrok
brew install ngrok
# Iniciar túnel
ngrok http 3000
ngrok te da un dominio temporal, p. ej. https://abc123.ngrok.io. Añádelo en WeChat Open Platform y actualiza NEXTAUTH_URL:
NEXTAUTH_URL=https://abc123.ngrok.io
Opción 2: archivo hosts
En /etc/hosts (Mac/Linux) o C:\Windows\System32\drivers\etc\hosts (Windows):
127.0.0.1 dev.yourdomain.com
Accede a http://dev.yourdomain.com:3000 y configura el dominio en WeChat. Pero WeChat exige dominio registrado (ICP), así que dev.yourdomain.com suele fallar. La opción 1 es más fiable.
Tratamiento especial de WeChat
WeChat no da email. Si tu app lo necesita:
async signIn({ user, account }) {
if (account?.provider === 'wechat') {
// Sin email: pedir al usuario que lo complete
// o usar openid como identificador único en la base de datos
console.log("openid de usuario WeChat:", user.id)
}
return true
}
Mejores prácticas de seguridad (evitar trampas habituales)
Tras configurar OAuth, cuida estos detalles. Yo los aprendí a base de errores.
1. client_secret nunca debe filtrarse
Mal:
// ❌ ¡Nunca hagas esto!
const clientSecret = "abc123def456" // hardcodeado
Si client_secret está en el frontend o en Git, cualquiera puede suplantar tu app.
Bien:
- Variables de entorno;
.env.localen.gitignore - client_secret solo en backend (las API routes de NextAuth.js cuentan como backend)
- En despliegue, variables del panel (Vercel → Settings → Environment Variables)
2. Para qué sirve state (anti-CSRF)
Un atacante puede enviarte un enlace con un code falso. Sin validar state, tu app podría cambiarlo por token.
NextAuth.js valida state automáticamente.
Si implementas OAuth a mano:
- Genera state aleatorio al iniciar y guárdalo en sesión o cookie
- En el callback, compara el state devuelto con el enviado
- Si no coinciden, rechaza
3. Lista blanca de URLs de callback
En Google, GitHub y WeChat, registra todas las URLs posibles:
- Desarrollo:
http://localhost:3000/api/auth/callback/[provider] - Preview:
https://preview.yourdomain.com/api/auth/callback/[provider] - Producción:
https://yourdomain.com/api/auth/callback/[provider]
No uses comodines (https://*.yourdomain.com): cómodo pero inseguro. Lista dominios concretos.
4. Seguridad al almacenar tokens
NextAuth.js guarda la sesión en JWT en cookies HttpOnly:
- HttpOnly: JavaScript del frontend no lee la cookie; reduce robo por XSS
- Secure (producción): solo por HTTPS; reduce ataques man-in-the-middle
Tu parte:
- No devuelvas access_token al frontend (NextAuth.js no lo hace por defecto; no lo expongas tú)
- Si persistes usuarios, hazlo en el callback
signInen base de datos; en sesión solo lo necesario (id, email)
5. Caducidad del código de autorización
El code caduca en ~10 minutos y solo vale una vez.
Aunque alguien lo intercepte, puede que ya esté caducado o usado.
Si el usuario tarda mucho en la pantalla de Google, el code puede expirar. NextAuth.js suele relanzar la autorización.
6. Checklist antes de producción
- ¿Variables de entorno listas (NEXTAUTH_URL, NEXTAUTH_SECRET, client_id y client_secret de cada provider)?
- ¿NEXTAUTH_URL apunta al dominio de producción (no localhost)?
- ¿URLs de callback de producción en cada proveedor OAuth?
- ¿
.env.localen.gitignore? - ¿NEXTAUTH_SECRET de producción generado al azar (distinto del de desarrollo)?
Resumen
OAuth, en el fondo, es un «pase temporal»: no das tu contraseña a apps de terceros; autorizas que pidan en el proveedor un token con caducidad y permisos limitados (access_token). Primero el code demuestra que el usuario aceptó; luego code + client_secret obtienen el token real.
En Next.js, Google es lo más fácil para empezar; GitHub un poco más fino (scope y emails no públicos); WeChat el más especial (QR, provider custom, dominio registrado, local incómodo).
En seguridad, tres reglas:
- client_secret solo en backend, nunca filtrado
- Validar state (NextAuth.js lo hace)
- Lista blanca de callbacks, sin comodines
Si es tu primera vez con OAuth, empieza por Google siguiendo el código de este artículo. Cuando funciona, la satisfacción compensa.
Si algo falla, no entres en pánico: el 90 % son redirect_uri mal configurado o variables de entorno faltantes. Repasa y suele resolverse.
Por último, mira la documentación oficial de NextAuth.js (sesión en base de datos, páginas de login custom, JWT, etc.). La especificación OAuth 2.0 (RFC 6749) también ayuda: entender la base facilita depurar.
¡Manos a la obra y mucha suerte con la configuración!
Flujo completo de configuración de inicio de sesión OAuth de terceros en Next.js
Configurar desde cero inicio de sesión con Google, GitHub y WeChat
⏱️ Estimated time: 2 hr
- 1
Step 1: Instalar e inicializar NextAuth.js
Instalar dependencias:
• npm install next-auth
• Crear app/api/auth/[...nextauth]/route.ts
Configuración básica:
• Definir NEXTAUTH_URL (local: http://localhost:3000, producción: dominio real)
• Definir NEXTAUTH_SECRET (generar cadena aleatoria)
• Configurar el array providers - 2
Step 2: Configurar inicio de sesión con Google
Pasos:
1. Acceder a Google Cloud Console
2. Crear un ID de cliente OAuth
3. Definir URI de redirección autorizada: http://localhost:3000/api/auth/callback/google
4. Obtener Client ID y Client Secret
5. Añadir a variables de entorno: GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET
6. Añadir GoogleProvider en la configuración de NextAuth
Nota: en producción la URL de callback debe coincidir exactamente con la configurada - 3
Step 3: Configurar inicio de sesión con GitHub
Pasos:
1. Ir a GitHub Settings > Developer settings > OAuth Apps
2. Crear una OAuth App
3. Definir Authorization callback URL: http://localhost:3000/api/auth/callback/github
4. Obtener Client ID y Client Secret
5. Añadir a variables de entorno: GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET
6. Añadir GitHubProvider en la configuración de NextAuth
Nota: el scope debe incluir user:email para obtener el correo - 4
Step 4: Configurar inicio de sesión con WeChat (opcional)
Pasos:
1. Registrar cuenta en WeChat Open Platform (requiere verificación empresarial)
2. Crear aplicación web y obtener AppID y AppSecret
3. Configurar dominio de callback autorizado (requiere registro ICP)
4. Provider personalizado (NextAuth no incluye WeChat)
5. Implementar flujo de inicio de sesión con código QR
Nota: WeChat es más complejo; conviene dominar Google y GitHub antes - 5
Step 5: Crear página y botones de inicio de sesión
Crear componente de login:
• Usar signIn('google') para iniciar sesión
• Usar signOut() para cerrar sesión
• Usar useSession() para obtener datos del usuario
• Envolver la app con SessionProvider
Ejemplo:
<button onClick={() => signIn('google')}>
Iniciar sesión con Google
</button> - 6
Step 6: Probar y depurar
Puntos de prueba:
• Local: asegurar que la URL de callback sea http://localhost:3000
• Producción: que la URL de callback coincida con el dominio real
• Comprobar variables de entorno
• Revisar consola del navegador y logs del servidor
Errores habituales:
• redirect_uri_mismatch: URL de callback no coincide
• invalid_client: Client ID o Secret incorrectos
• access_denied: el usuario rechazó la autorización
FAQ
¿Cómo funciona OAuth 2.0?
¿Cómo solucionar el error redirect_uri_mismatch?
Solución:
1) La URL configurada en el panel del proveedor OAuth debe coincidir exactamente con la del código (protocolo, dominio, puerto y ruta)
2) En desarrollo local usa http://localhost:3000; en producción, el dominio real
3) Revisa barras finales o parámetros extra
¿Qué diferencia hay entre NextAuth.js e implementar OAuth manualmente?
• Soporta más de 50 proveedores
• Gestiona automáticamente el flujo de autorización, sesiones y protección CSRF
La implementación manual exige manejar:
• Intercambio del código de autorización
• Almacenamiento de tokens
• Validación de state
Mucho más código y propenso a errores; se recomienda NextAuth.js.
¿Cómo obtener el correo del usuario?
• Google: devuelve el correo por defecto
• GitHub: el scope debe incluir user:email y el usuario debe tener el correo público
• WeChat: hay que consultarlo vía unionid
Si no se obtiene, puedes pedir al usuario que lo complete tras el login.
¿Funciona en local pero falla en producción?
Comprueba:
1) Si NEXTAUTH_URL en producción es correcto
2) Si el panel del proveedor OAuth incluye el dominio de producción
3) Si las variables de entorno están bien definidas
4) Si un firewall o proxy interfiere
¿Se pueden soportar varios métodos de inicio de sesión a la vez?
¿Es seguro el inicio de sesión OAuth?
Pero hay que cuidar:
1) client_secret debe ser confidencial y usarse solo en el servidor
2) Usar el parámetro state contra CSRF (NextAuth.js lo gestiona)
3) Lista blanca de URLs de callback, sin comodines
4) Actualizar dependencias con regularidad
16 min de lectura · Publicado el: 19 dic 2025 · Actualizado el: 21 ago 2026
Guía completa de Next.js
Si llegaste desde búsqueda, lo más rápido es ir al artículo anterior o siguiente de esta misma serie.
Anterior
Protección de rutas y control de permisos en Next.js: guía completa de Middleware y defensa en profundidad
Análisis profundo de la protección de rutas y el control de permisos en Next.js, desde Middleware hasta una arquitectura de defensa en profundidad, con NextAuth y getServerSession para un sistema RBAC seguro y ejemplos de código completos.
Parte 12 de 51
Siguiente
Inicio de sesión OAuth en Next.js: guía práctica para Google, GitHub y WeChat
Del principio de OAuth a la configuración práctica: entiende el flujo de autorización con la analogía de recoger un paquete e implementa paso a paso Google, GitHub y WeChat con NextAuth.js, con guía completa de resolución de errores.
Parte 14 de 51



Comentarios
Inicia sesión con GitHub para dejar un comentario