Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

367
Visualizações
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 Respostas
Responde à pergunta

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 Relatório

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 Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda