Así que estoy creando una lógica de autenticación en mi aplicación Next.js. Creé la página /api/auth/login
donde manejo la solicitud y si los datos del usuario son buenos, estoy creando una cookie httpOnly
con token JWT y devolviendo algunos datos a la interfaz. Esa parte funciona bien, pero necesito alguna forma de proteger algunas páginas para que solo los usuarios registrados puedan acceder a ellas y tengo problemas para crear un HOC para eso.
La mejor manera que vi es usar getInitialProps
pero en el sitio Next.js dice que ya no debería usarlo, así que pensé en usar getServerSideProps
pero eso tampoco funciona o probablemente esté haciendo algo mal.
Este es mi código HOC: (las cookies se almacenan bajo el nombre userToken
de usuario)
import React from 'react'; const jwt = require('jsonwebtoken'); const RequireAuthentication = (WrappedComponent) => { return WrappedComponent; }; export async function getServerSideProps({req,res}) { const token = req.cookies.userToken || null; // no token so i take user to login page if (!token) { res.statusCode = 302; res.setHeader('Location', '/admin/login') return {props: {}} } else { // we have token so i return nothing without changing location return; } } export default RequireAuthentication;
Si tiene alguna otra idea sobre cómo manejar la autenticación en Next.js con cookies, le agradecería que me ayudara porque soy nuevo en la representación del lado del servidor reaccionar/autenticación.
Debe separar y extraer su lógica de autenticación de getServerSideProps
en una función reutilizable de orden superior.
Por ejemplo, podría tener la siguiente función que aceptaría otra función (su getServerSideProps
) y redirigiría a su página de inicio de sesión si el userToken
de usuario no está configurado.
export function requireAuthentication(gssp) { return async (context) => { const { req, res } = context; const token = req.cookies.userToken; if (!token) { // Redirect to login page return { redirect: { destination: '/admin/login', statusCode: 302 } }; } return await gssp(context); // Continue on to call `getServerSideProps` logic } }
Luego lo usaría en su página envolviendo la función getServerSideProps
.
// pages/index.js (or some other page) export const getServerSideProps = requireAuthentication(context => { // Your normal `getServerSideProps` code here })
Basado en la respuesta de Julio, lo hice funcionar para iron-session
:
import { GetServerSidePropsContext } from 'next' import { withSessionSsr } from '@/utils/index' export const withAuth = (gssp: any) => { return async (context: GetServerSidePropsContext) => { const { req } = context const user = req.session.user if (!user) { return { redirect: { destination: '/', statusCode: 302, }, } } return await gssp(context) } } export const withAuthSsr = (handler: any) => withSessionSsr(withAuth(handler))
Y luego lo uso como:
export const getServerSideProps = withAuthSsr((context: GetServerSidePropsContext) => { return { props: {}, } })
Mi función withSessionSsr
se ve así:
import { GetServerSidePropsContext, GetServerSidePropsResult, NextApiHandler } from 'next' import { withIronSessionApiRoute, withIronSessionSsr } from 'iron-session/next' import { IronSessionOptions } from 'iron-session' const IRON_OPTIONS: IronSessionOptions = { cookieName: process.env.IRON_COOKIE_NAME, password: process.env.IRON_PASSWORD, ttl: 60 * 2, } function withSessionRoute(handler: NextApiHandler) { return withIronSessionApiRoute(handler, IRON_OPTIONS) } // Theses types are compatible with InferGetStaticPropsType https://nextjs.org/docs/basic-features/data-fetching#typescript-use-getstaticprops function withSessionSsr<P extends { [key: string]: unknown } = { [key: string]: unknown }>( handler: ( context: GetServerSidePropsContext ) => GetServerSidePropsResult<P> | Promise<GetServerSidePropsResult<P>> ) { return withIronSessionSsr(handler, IRON_OPTIONS) } export { withSessionRoute, withSessionSsr }