Saltar al contenido principal

Usa IA para integrar Auth0

Si usas un asistente de codificación con IA como Claude Code, Cursor o GitHub Copilot, puedes añadir la autenticación de Auth0 automáticamente en cuestión de minutos con agent skills.Instalar:
npx skills add auth0/agent-skills --skill auth0-quickstart --skill auth0-nextjs
Luego, pídele a tu asistente de IA:
Add Auth0 authentication to my Next.js app
Tu asistente de IA creará automáticamente tu aplicación de Auth0, obtendrá las credenciales, instalará @auth0/nextjs-auth0, creará rutas de API y configurará las variables de entorno. Documentación completa de agent skills →
Requisitos previos: Antes de comenzar, asegúrate de tener instalado lo siguiente:Verifica la instalación: node --version && npm --version

Primeros pasos

Este inicio rápido muestra cómo añadir autenticación de Auth0 a una aplicación Next.js 16. Crearás una aplicación web full-stack con renderizado del lado del servidor, inicio de sesión seguro y rutas protegidas mediante el SDK de Auth0 Next.js v4.
1

Cree un nuevo proyecto

Crea un proyecto nuevo de Next.js para este inicio rápido
npx create-next-app@latest auth0-nextjs --typescript --tailwind --eslint --app --src-dir --import-alias "@/*" --yes
Abra el proyecto
cd auth0-nextjs
2

Instala el SDK de Auth0 para Next.js

shellscript npm install @auth0/nextjs-auth0
3

Crear los archivos del proyecto

Cree todos los directorios y archivos necesarios para la integración con Auth0:
mkdir -p src/lib src/components && touch src/lib/auth0.ts src/proxy.ts src/components/LoginButton.tsx src/components/LogoutButton.tsx src/components/Profile.tsx
4

Configura tu aplicación de Auth0

A continuación, debes crear una nueva aplicación en tu tenant de Auth0 y agregar las variables de entorno a tu proyecto.Tienes tres opciones para configurar tu aplicación de Auth0: usar la herramienta Quick Setup (recomendado), ejecutar un comando de CLI o configurar manualmente a través del Dashboard:
Crea una aplicación de Auth0 y copia el archivo .env ya completado con los valores de configuración correctos.
5

Crear la configuración de Auth0

Agrega el código del cliente de Auth0 en src/lib/auth0.ts:
src/lib/auth0.ts
import { Auth0Client } from '@auth0/nextjs-auth0/server';

export const auth0 = new Auth0Client();
6

Añadir proxy

Agrega el código del proxy a src/proxy.ts:
src/proxy.ts
import { auth0 } from "./lib/auth0";

export async function proxy(request: Request) {
  return await auth0.middleware(request);
}

export const config = {
  matcher: [
    /*
     * Coincide con todas las rutas de solicitud excepto las que comienzan con:
     * - _next/static (archivos estáticos)
     * - _next/image (archivos de optimización de imágenes)
     * - favicon.ico, sitemap.xml, robots.txt (archivos de metadatos)
     */
    "/((?!_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
  ],
};
Como estamos usando un directorio src/, el archivo proxy.ts se crea dentro de src/. Si no usas un directorio src/, créalo en la raíz del proyecto.
Este proxy monta automáticamente las siguientes rutas de autenticación:
  • /auth/login - Ruta de inicio de sesión
  • /auth/logout - Ruta de cierre de sesión
  • /auth/callback - Ruta de callback
  • /auth/profile - Ruta del perfil de usuario
  • /auth/access-token - Ruta del token de acceso
  • /auth/backchannel-logout - Ruta de cierre de sesión por backchannel
7

Crear componentes de inicio de sesión, cierre de sesión y perfil

Agrega el código del componente a los archivos creados en el paso 3:
8

Actualiza tu página principal

Reemplaza src/app/page.tsx con:
src/app/page.tsx
import { auth0 } from "@/lib/auth0";
import LoginButton from "@/components/LoginButton";
import LogoutButton from "@/components/LogoutButton";
import Profile from "@/components/Profile";

export default async function Home() {
  const session = await auth0.getSession();
  const user = session?.user;

  return (
    <main className="min-h-screen bg-[#efefef] flex flex-col items-center justify-center gap-4 px-6 py-12">
      <div className="bg-white rounded-[28px] shadow-[0_4px_32px_rgba(0,0,0,0.08)] px-12 py-14 flex flex-col items-center gap-4 w-[360px]">
        <svg width="68" height="68" viewBox="0 0 68 68" fill="none" xmlns="http://www.w3.org/2000/svg" className="mb-1">
          <g filter="url(#filter0_di)">
            <rect x="2" y="2" width="64" height="64" rx="16" fill="url(#paint0_linear)"/>
            <rect x="2.5" y="2.5" width="63" height="63" rx="15.5" stroke="#252525"/>
            <path d="M34.0002 18C25.1572 18 18 25.1669 18 34C18 42.8432 25.1672 50 34.0002 50C42.8333 50 50 42.8331 50 34C50 25.1669 42.8433 18 34.0002 18ZM43.9172 43.8971C43.9172 43.9071 43.9069 43.9072 43.9069 43.9172C43.9069 43.9172 43.8969 43.9272 43.8868 43.9272C43.144 44.65 41.9796 44.7303 41.0662 44.2585L40.0228 43.7265C36.2487 41.7792 31.7619 41.7792 27.9777 43.7265L26.9338 44.2585C26.0103 44.7303 24.8459 44.65 24.1132 43.9272C24.1132 43.9272 24.1031 43.9172 24.0931 43.9172C24.0931 43.9172 24.0828 43.9071 24.0828 43.8971C23.3601 43.1543 23.2797 41.9899 23.7515 41.0765L24.2837 40.0326C26.231 36.2585 26.231 31.7717 24.2837 27.9975L23.7515 26.9536C23.2797 26.0302 23.3601 24.8657 24.0828 24.133C24.0828 24.1229 24.0931 24.123 24.0931 24.123C24.0931 24.123 24.1031 24.1129 24.1132 24.1129C24.856 23.3902 26.0204 23.3099 26.9338 23.7817L27.9777 24.3137C31.7518 26.261 36.2386 26.261 40.0228 24.3137L41.0662 23.7817C41.9897 23.3099 43.1541 23.3902 43.8868 24.1129C43.8868 24.1129 43.8969 24.123 43.9069 24.123L43.9172 24.133C44.6399 24.8758 44.7203 26.0402 44.2485 26.9536L43.7163 27.9975C41.769 31.7717 41.769 36.2585 43.7163 40.0326L44.2485 41.0765C44.7203 41.9899 44.6499 43.1543 43.9172 43.8971Z" fill="white"/>
          </g>
          <defs>
            <filter id="filter0_di" x="0" y="0" width="68" height="68" filterUnits="userSpaceOnUse" colorInterpolationFilters="sRGB">
              <feFlood floodOpacity="0" result="BackgroundImageFix"/>
              <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
              <feMorphology radius="2" operator="dilate" in="SourceAlpha" result="effect1_dropShadow"/>
              <feOffset/>
              <feComposite in2="hardAlpha" operator="out"/>
              <feColorMatrix type="matrix" values="0 0 0 0 0.117647 0 0 0 0 0.129412 0 0 0 0 0.164706 0 0 0 0.12 0"/>
              <feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
              <feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
              <feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
              <feOffset dy="-1"/>
              <feGaussianBlur stdDeviation="0.5"/>
              <feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
              <feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
              <feBlend mode="normal" in2="shape" result="effect2_innerShadow"/>
            </filter>
            <linearGradient id="paint0_linear" x1="34" y1="2" x2="34" y2="66" gradientUnits="userSpaceOnUse">
              <stop/>
              <stop offset="1" stopColor="#677190"/>
            </linearGradient>
          </defs>
        </svg>

        {user ? (
          <>
            <h1 className="text-[17px] font-bold text-gray-900 tracking-tight">Your account</h1>
            <div className="w-full h-px bg-gray-100" />
            <Profile />
            <LogoutButton />
          </>
        ) : (
          <>
            <h1 className="text-[17px] font-bold text-gray-900 tracking-tight">Welcome to Sample0</h1>
            <p className="text-[13px] text-gray-400 text-center leading-relaxed -mt-2">
              Get started by logging in to your account
            </p>
            <div className="h-3" />
            <LoginButton />
          </>
        )}
      </div>

      <div className="flex items-center gap-1.5 text-[11px] text-gray-400">
        <span>Powered by</span>
        <img
          src="https://cdn.auth0.com/quantum-assets/dist/latest/logos/auth0/auth0-lockup-en-onlight.svg"
          alt="Auth0"
          className="h-3 opacity-40"
        />
      </div>
    </main>
  );
}
9

Actualiza el layout con Auth0Provider

Actualiza src/app/layout.tsx para cargar la fuente Inter y envolver la aplicación con Auth0Provider:
src/app/layout.tsx
import { Inter } from "next/font/google";
import type { Metadata } from "next";
import { Auth0Provider } from "@auth0/nextjs-auth0/client";
import "./globals.css";

const inter = Inter({
  subsets: ["latin"],
  weight: ["300", "400", "500", "600", "700"],
});

export const metadata: Metadata = {
  title: "Auth0 Next.js App",
  description: "Next.js app with Auth0 authentication",
};

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body className={inter.className}>
        <Auth0Provider>{children}</Auth0Provider>
      </body>
    </html>
  );
}
En la v4, Auth0Provider es opcional. Solo lo necesitas si quieres pasar un usuario inicial durante el renderizado en el servidor para que esté disponible en el hook useUser().
10

Configura Tailwind CSS

Reemplaza el contenido de src/app/globals.css con:
src/app/globals.css
@import "tailwindcss";
11

Ejecuta tu aplicación

npm run dev
Tu aplicación estará disponible en http://localhost:3000. El SDK v4 de Auth0 configura automáticamente las rutas de autenticación en /auth/* (no en /api/auth/*, como en la v3).Si el puerto 3000 ya está en uso, ejecuta: npm run dev -- --port 3001 y actualiza las URL de callback de tu aplicación de Auth0 a http://localhost:3001
Punto de controlAhora deberías tener una página de inicio de sesión de Auth0 completamente funcional en ejecución en tu localhost

Solución de problemas

Si ves el error JWEDecryptionFailed: decryption operation failed, suele deberse a que AUTH0_SECRET no es válido o a que hay una cookie de sesión antigua cifrada con un secreto distinto.Solución:
  1. Genera un secreto nuevo con:
openssl rand -hex 32
  1. Actualiza tu archivo .env.local:
AUTH0_SECRET=<tu-nueva-cadena-hexadecimal-de-64-caracteres>
  1. Borra las cookies del navegador para localhost:3000:
    • Chrome/Edge: Presiona F12 → pestaña Application → Cookies → elimina todas las cookies de localhost
    • Firefox: Presiona F12 → pestaña Storage → Cookies → elimina todas las cookies de localhost
    • Safari: menú Develop → Show Web Inspector → pestaña Storage → Cookies → Delete all
  2. Reinicia el servidor de desarrollo:
npm run dev
El secreto debe tener exactamente 32 bytes (64 caracteres hexadecimales). El error se produce cuando la aplicación intenta descifrar una cookie de sesión existente que se cifró con un secreto distinto.
Si al hacer clic en iniciar sesión llegas a una página 404, revisa estos problemas habituales:
  1. Ubicación del proxy: Asegúrate de que src/proxy.ts exista en la ubicación correcta
  2. Código del proxy: Verifica que el proxy coincida con el código del paso 6
  3. Reinicia el servidor: Después de crear el archivo proxy, reinicia el servidor de desarrollo
  4. Comprueba las importaciones: Asegúrate de que la ruta import { auth0 } from "./lib/auth0" sea correcta
Si ves “Cannot find module ’@/components/LoginButton’” o errores similares:
  1. Verifica que los archivos existan: Comprueba que se hayan creado todos los archivos del paso 3
  2. Revisa las rutas: Asegúrate de que los componentes estén en el directorio src/components/
  3. Reinicia TypeScript: Presiona Cmd+Shift+P (Mac) o Ctrl+Shift+P (Windows) y ejecuta “TypeScript: Restart TS Server”
  4. Comprueba las importaciones: Asegúrate de que estás usando @/components/* (no ~/components/*)

Uso avanzado

Este inicio rápido usa Auth0 Next.js SDK v4, que incorpora cambios importantes con respecto a v3:
  • No se necesitan controladores de rutas dinámicas - El proxy monta automáticamente las rutas de autenticación
  • Configuración simplificada del cliente - new Auth0Client() lee automáticamente las variables de entorno
  • Nuevas rutas - Las rutas están en /auth/* en lugar de /api/auth/*
  • Proxy obligatorio - Toda la funcionalidad de autenticación pasa por proxy.ts
  • Usa etiquetas <a> - La navegación debe usar <a href="/auth/login"> en lugar de botones con onClick

Rutas de autenticación

El SDK monta automáticamente estas rutas a través del proxy:
RutaPropósito
/auth/loginIniciar sesión
/auth/logoutCerrar la sesión del usuario
/auth/callbackGestionar el callback de Auth0
/auth/profileObtener el perfil del usuario
/auth/access-tokenObtener el token de acceso
/auth/backchannel-logoutGestionar el cierre de sesión por canal secundario
Si ves errores 404 en estas rutas, asegúrate de que:
  1. El archivo proxy.ts esté en la ubicación correcta (la raíz del proyecto o dentro de src/ si usas un directorio src/)
  2. El proxy esté configurado correctamente con el patrón matcher que se muestra en el paso 6
  3. El servidor de desarrollo se haya reiniciado después de crear el archivo del proxy
Auth0 Next.js SDK v4 admite tanto los patrones de App Router como los de Pages Router. Estos son algunos patrones habituales del lado del servidor:
app/protected/page.tsx
import { auth0 } from "@/lib/auth0";
import { redirect } from "next/navigation";

export default async function ProtectedPage() {
  const session = await auth0.getSession();

  if (!session) {
    redirect('/auth/login');
  }

  return (
    <div>
      <h1>Protected Content</h1>
      <p>Welcome, {session.user.name}!</p>
    </div>
  );
}
Para gestionar el estado de autenticación del lado del cliente, usa el hook useUser:
components/UserProfile.tsx
"use client";

import { useUser } from "@auth0/nextjs-auth0/client";

export default function UserProfile() {
  const { user, error, isLoading } = useUser();

  if (isLoading) return <div>Loading...</div>;
  if (error) return <div>Error: {error.message}</div>;
  if (!user) return <div>Not logged in</div>;

  return (
    <div>
      <h2>{user.name}</h2>
      <p>{user.email}</p>
      <img src={user.picture} alt="Profile" referrerPolicy="no-referrer" />
    </div>
  );
}
Para proteger rutas de API, usa el método withApiAuthRequired:
app/api/protected/route.ts
import { auth0 } from "@/lib/auth0";

export const GET = auth0.withApiAuthRequired(async function handler() {
  const session = await auth0.getSession();

  return Response.json({
    message: "This is a protected API route",
    user: session?.user
  });
});
Si usas un servicio backend de terceros (como Convex, Supabase o Firebase) que requiere tokens de autenticación de Auth0, tendrás que pasar el token de acceso desde tu aplicación Next.js al cliente del backend.

Obtención del Token de acceso

En el servidor (App Router):
app/api/token/route.ts
import { auth0 } from "@/lib/auth0";
import { NextResponse } from "next/server";

export async function GET() {
  const session = await auth0.getSession();

  if (!session) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const accessToken = session.accessToken;
  return NextResponse.json({ accessToken });
}
En el cliente:
lib/convex-client.ts
"use client";

import { ConvexProviderWithAuth0 } from "convex/react-auth0";
import { ConvexReactClient } from "convex/react";

const convex = new ConvexReactClient(process.env.NEXT_PUBLIC_CONVEX_URL!);

export function ConvexClientProvider({ children }: { children: React.ReactNode }) {
  return (
    <ConvexProviderWithAuth0
      client={convex}
      useAuth0={() => ({
        // Obtén el token de acceso desde la ruta de API de tu aplicación Next.js
        getAccessToken: async () => {
          const response = await fetch("/api/token");
          const { accessToken } = await response.json();
          return accessToken;
        },
      })}
    >
      {children}
    </ConvexProviderWithAuth0>
  );
}

Configuración del backend

La mayoría de los servicios de terceros necesitan tu dominio y audiencia de Auth0 para verificar los tokens. En la configuración del backend:
convex/auth.config.ts
export default {
  providers: [
    {
      domain: process.env.AUTH0_DOMAIN,
      applicationID: process.env.AUTH0_CLIENT_ID,
    },
  ],
};
Asegúrate de que tu aplicación de Auth0 esté configurada con una audiencia de API si tu backend la requiere. Puedes configurarla en Auth0 Dashboard, en Applications → APIs, o agregar AUTH0_AUDIENCE a tu .env.local y configurar el SDK en consecuencia.

Solución de problemas con tokens

Si ctx.auth.getUserIdentity() devuelve null en tu backend:
  1. Verifica que se esté enviando el token: revisa la pestaña Network de las herramientas de desarrollo del navegador para confirmar que el token se incluya en las solicitudes
  2. Comprueba el formato del token: asegúrate de enviar el accessToken, no el idToken
  3. Verifica la configuración del backend: confirma que tu backend tenga el dominio de Auth0 y el ID de cliente correctos
  4. Comprueba la audiencia: si usas una API de Auth0, asegúrate de que AUTH0_AUDIENCE esté configurado y coincida con el identificador de tu API
  5. Inspecciona los claims del token: decodifica tu JWT en jwt.io para verificar que contiene los claims esperados