Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

364
Views
Construyendo un tablero en Next.js: ¿mejores prácticas para hacer que las páginas sean privadas con roles, sin "parpadeo", usando la autenticación JWT?

Teniendo en cuenta que tenemos:

  • Un backend ya listo (no en Next) con autenticación mediante patrón JWT y un RBAC casero
  • 4 páginas privadas solo para personas no autenticadas (iniciar sesión, registrarse, contraseña olvidada, restablecer contraseña)
  • ~25+ páginas privadas para el tablero
  • 1 página pública para la presentación del tablero
  • Cientos de componentes relacionados con el tablero (+ miles de componentes del sistema de diseño)

Los usuarios deben:

  • iniciar sesión antes de acceder al tablero
  • si no está autenticado y accede a una ruta privada, debe redirigirse a /login sin parpadear
  • si está autenticado y accede a rutas para usuarios no autenticados, debe redirigirse a /profile sin parpadear)

Mi lógica en este momento para tratar con JWT:

 // lib/axios.js import Axios from 'axios'; import { getCookie, removeCookies } from 'cookies-next'; import qs from 'qs'; export const axios = Axios.create({ baseURL: process.env.NEXT_PUBLIC_API_URL, paramsSerializer: (params) => qs.stringify(params, { arrayFormat: 'brackets' }), withCredentials: true, }); axios.interceptors.request.use( (config) => { const token = getCookie('access_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; config.headers.Accept = 'application/json'; } return config; }, (error) => { return Promise.reject(error); } ); axios.interceptors.response.use( (response) => response, async (error) => { if (error.response.status === 401) { // we need to implement refresh pattern // const refresh = await refreshToken(); removeCookies('access_token'); } return Promise.reject(error); } ); // For SWR export const fetcher = async (...args) => await axios.get(...args).data;

He estado acumulando investigaciones sobre esto y encontré muchas respuestas diferentes. Hasta ahora encontré:

  • Proveedor para colocar _app.js con rutas privadas codificadas en una matriz
  • Diferentes funciones HoC dentro de cada página como withPrivate o withPublic
  • Usando getServerSideProps con redirección para iniciar sesión dentro de cada página
  • nextAuth pero no estoy seguro porque parece que está construyendo un backend y ya tenemos uno
  • _middleware que aparentemente puede hacer la redirección
  • Parece que es posible usar SWR , Suspense y Error Boundaries pero no estoy seguro si es adecuado para este tipo de casos...

alguna pista de como debo hacer?

about 4 years ago · Juan Pablo Isaza
2 answers
Answer question

0

Si no usa la generación estática y nunca planea, getServerSideProps funciona.

Si planea usar Vercel para hospedar, _middleware podría ser una buena opción; sin embargo, el soporte de hospedaje de terceros se está quedando atrás.

Como ya tiene su propia autenticación, nextAuth no parece ser una buena opción.

Recomiendo usar un contexto Auth: ya no es necesario envolver cada página con un HOC.

Puede evitar el parpadeo utilizando una pantalla de carga o un control giratorio.


Este es un ejemplo de un contexto de autenticación.

 import { useEffect, useState, useCallback, createContext } from "react"; import { useRouter } from "next/router"; const AuthContext = createContext(null); export const AuthProvider = ({ children }) => { const { asPath, push } = useRouter(); const [user, setUser] = useState(null); // if you use trailing slash you'd need to add them to each route const isAuthRoute = ["/login", "/signup", "/forgot", "/reset"].includes(asPath); const redirectToLogin = useCallback(async () => { try { setUser(null); await push('/login'); } catch (e) { console.error("Could not redirect to login"); } }, [push]); const signOut = async () => { try { await authServiceSignout(); await redirectToLogin(); } catch { window.location.reload(); } }; const goHome = useCallback(() => push('/'), [push]); // check if user is logged in on every route changes and // redirect accordingly useEffect(() => { const getUser = async () => { const user = await getUserOrJWT(); if (user) { setUser(user); // user details if (isAuthRoute) await goHome(); } else if (!isAuthRoute) { await redirectToLogin(); } }; getUser(); }, [asPath, goHome, isAuthRoute, redirectToLogin]); if (!user && isAuthRoute) return <>{children}</>; if (!user) return <>Loading or loading spinner</>; return ( <AuthContext.Provider value={{ user, signOut }}> {children} </AuthContext.Provider> ); };

Eliminé un montón de código, por lo que probablemente no funcione copiar y pegar directamente, pero puedes hacerte una idea.

isAuthRoute solo necesita devolver verdadero/falso, por lo que otras buenas opciones si todas las rutas de su panel comienzan con /dashboard , puede usar asPath.startsWith('/dashboard') en su lugar.

Procesamos condicionalmente el contexto de autenticación porque no es necesario en las páginas públicas y también borra el contexto del usuario al cerrar la sesión para que no tengamos que preocuparnos por la filtración de datos antiguos del usuario a través del contexto.

También usamos el almacenamiento local y el canal de transmisión de la ventana para escuchar las llamadas de cierre de sesión. Esto nos permite cerrar la sesión del usuario en cada pestaña y ventana.

about 4 years ago · Juan Pablo Isaza Report

0

Después de muchas pruebas con diferentes técnicas, decidí optar por la nueva característica increíble de Next.js.

Si alguien tiene problemas con este tema como lo hice yo, aquí está mi código:

 // _middleware.js in /pages, works also with Typescript .ts import { NextResponse } from 'next/server'; import { isAuthValid } from '@/lib/auth' export function middleware(req) { if ( req.nextUrl.pathname.startsWith('/login') || req.nextUrl.pathname.startsWith('/signup') || req.nextUrl.pathname.startsWith('/forgot') || req.nextUrl.pathname.startsWith('/reset') ) { if (isAuthValid(req)) { return NextResponse.redirect(new URL('/profile', req.url)); } return NextResponse.next(); } // All other routes if (isAuthValid(req)) { return NextResponse.next(); } return NextResponse.redirect( new URL(`/login?from=${req.nextUrl.pathname}`, req.url) ); }

Sin embargo, tenga cuidado ya que el nombre y la ubicación de este archivo cambiarán en la nueva versión Next.js 12.2 , bajo el nombre de middleware.js (o .ts ) en su carpeta raíz, ya sea raíz o src , según su configuración.

about 4 years ago · Juan Pablo Isaza Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!