¿Qué es la autenticación Next.js?

La autenticación Next.js es el proceso de verificación de la identidad del usuario en las aplicaciones Next.js. Garantiza que sólo los usuarios autorizados puedan acceder a rutas y datos protegidos.

La autenticación en Next.js es crucial para:

  1. Proteger los datos sensibles de los usuarios
  2. Controlar el acceso a funciones específicas
  3. Personalizar la experiencia del usuario
  4. Mantener la seguridad de la aplicación

Comprender las mejores prácticas de autenticación en Next.js es clave para crear aplicaciones web seguras y eficientes.

Autenticación por middleware frente a autenticación por componentes de página

Next.js proporciona dos enfoques principales para la autenticación: middleware y autenticación de componentes de página. Exploremos ambos:

Autenticación middleware

La autenticación middleware ofrece varias ventajas:

  • Estructura más limpia para gestionar la autenticación a través de rutas
  • Preserva las capacidades de renderizado estático
  • Mejor rendimiento, especialmente con tokens web JSON (JWT).

He aquí un ejemplo sencillo de autenticación middleware:

import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  const currentUser = request.cookies.get('currentUser')?.value
 
  if (currentUser && !request.nextUrl.pathname.startsWith('/dashboard')) {
    return Response.redirect(new URL('/dashboard', request.url))
  }
 
  if (!currentUser && !request.nextUrl.pathname.startsWith('/login')) {
    return Response.redirect(new URL('/login', request.url))
  }
}
 
export const config = {
  matcher: ['/((?!api|_next/static|_next/image|.*\\.png$).*)'],
}

Autenticación de componentes de página

La autenticación de componentes de página tiene sus propias ventajas:

  • Puede implementarse directamente en el archivo de página
  • Ofrece más flexibilidad para la lógica de autenticación específica de la página

He aquí un ejemplo de autenticación de componentes de página:

import { redirect } from 'next/navigation';
import { checkAuth } from '@/lib/auth';

export default async function ProtectedPage() {
  const isAuthenticated = await checkAuth();
  if (!isAuthenticated) {
    redirect('/login');
  }
  return (
    <div>
      <h1>Protected Content</h1>
      {/* Page content here */}
    </div>
  );
}

Consejo: Elige middleware para un mejor rendimiento y una estructura de código más limpia, especialmente para apps con muchas rutas protegidas.

Cómo evitar la autenticación en los componentes de diseño

Es importante evitar implementar comprobaciones de autenticación en los layout components. ¿Por qué? Los componentes de diseño no se vuelven a renderizar al navegar por el lado del cliente, lo que podría dejar rutas desprotegidas.

Preservar el renderizado estático

El renderizado estático es una característica clave del rendimiento de Next.js. Para preservarla

  1. Utilizar middleware para la autenticación cuando sea posible.
  2. No añadas autenticación dentro de rutas específicas (páginas).

Añadir autenticación dentro de una página la hace dinámica. Sin embargo, muchas veces el beneficio extra de la capa de seguridad supera la mejora del rendimiento.

Autenticación para acciones de servidor

Las acciones del servidor son una nueva característica de Next.js que permite el procesamiento del lado del servidor directamente desde los componentes del cliente. Al utilizar acciones de servidor:

  1. Implementa comprobaciones de autenticación dentro de la propia acción de servidor
  2. No confíes únicamente en la autenticación a nivel de página o middleware.

Las acciones de servidor son como las rutas API.
Pueden ser llamadas por un usuario externo llamando directamente a la URL de la acción del servidor.

Principio de proximidad.

El principio de proximidad sugiere mantener las comprobaciones de autenticación lo más cerca posible del lugar en el que se accede a los datos o se utilizan. Esto significa

  1. Implementar comprobaciones en componentes reutilizables que manejen datos sensibles.
  2. Añadir lógica de autenticación directamente en las funciones de obtención de datos.

He aquí un ejemplo de aplicación del principio de proximidad:

 async function fetchUserData(userId: string) {
	const isAuthenticated = await checkAuth();
  if (!isAuthenticated) {
    throw new Error('Unauthorized');
  }

  // Fetch and return user data
}

Enfoque multicapa

Una estrategia de autenticación robusta en Next.js implica múltiples capas de protección:

  1. Utilizar middleware o comprobaciones a nivel de página como primera línea de defensa
  2. Implementar comprobaciones adicionales a nivel de página y de acceso a datos

He aquí un ejemplo simplificado de un enfoque multicapa:

 // Middleware (first layer)
export function middleware(request: NextRequest) {
  // Check for auth token
}

// Page component (second layer)
export default function ProtectedPage() {
  const { user } = useUser(); // Custom hook for user data
  if (!user) return <LoadingOrRedirect />;

  return <ProtectedContent user={user} />;
}

// Data fetching (third layer)
async function fetchSensitiveData() {
  // Check auth and permissions before fetching
}

Conclusión

Las mejores prácticas de autenticación de Next.js implican una combinación de técnicas:

  1. Utilizar middleware para autenticación en toda la aplicación cuando sea posible
  2. Implementar comprobaciones a nivel de página para rutas específicas
  3. Aplicar el principio de proximidad para el acceso a datos

Fuente