es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

La cookie “HttpOnly” aparece en el encabezado de respuesta pero no se está guardando en el navegador.

Recientemente construí una aplicación de chat en tiempo real simple con Nextjs en el frontend y Express en el backend. El frontend está desplegado en Vercel mientras que el backend está desplegado en Heroku. Cuando un usuario inicia sesión en la aplicación, el backend genera un token jwt que luego se envía a través de una cookie HttpOnly de regreso al frontend. Aquí está el código para dicha respuesta:

const authenticate = async (req, res, next) => {
  userService
    .authenticate(req)
    .then((user) => {
      const { token, ...userInfo } = user;
      res
        .setHeader(
          "Set-Cookie",
          cookie.serialize("token", token, {
            httpOnly: true,
            secure: process.env.NODE_ENV !== "development",
            maxAge: 60 * 60 * 24,
            sameSite: "none",
            path: "/",
          })
        )
        .status(200)
        .json(userInfo);
    })
    .catch(next);
};

Después de la autenticación, cada solicitud posterior al backend debe enviar el token para asegurarse de que el usuario ha iniciado sesión. Por ejemplo, esta es la solicitud enviada al servidor para obtener un chat entre el usuario conectado y otro usuario.

const getChat = async (id) => {
  const identification = id;
  const response = await axios.get(
    "<url_del_servidor>/chats/chat/${identification}",
    { withCredentials: true }
  );

  return response;
};

En desarrollo, cuando se encuentra en localhost:3000 para el frontend y en localhost:4000 para el backend, todo funciona bien. Sin embargo, cuando desplegué el frontend en Vercel y el backend en Heroku, ¡el navegador simplemente se niega a guardar la cookie! El token jwt aparece en el encabezado de la respuesta después de enviar la solicitud de autenticación, pero no se guarda en el navegador. He intentado absolutamente todo lo que se me ocurre, incluido cambiar los parámetros de la cookie, pero no puedo hacer que funcione. Estoy bastante seguro de que tengo la configuración de cors correctamente en el backend, junto con el módulo cookie-parser:

const cors = require("cors");
const cookieParser = require("cookie-parser");

app.use(
  cors({
    origin: "<url_del_cliente>",
    credentials: true,
  })
);

app.use(cookieParser());

Gracias por tomarse el tiempo para leer esto, ¡cualquier ayuda sería muy apreciada! Y mis disculpas si no he elaborado lo suficiente, ¡esta es mi primera publicación aquí y todavía estoy tratando de aprender la etiqueta adecuada del sitio!

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Problema con la cookie HttpOnly que no se guarda en el navegador

    Un desarrollador construyó una aplicación de chat en tiempo real con Nextjs en el frontend y Express en el backend. El frontend está desplegado en Vercel mientras que el backend está desplegado en Heroku. Cuando un usuario inicia sesión en la aplicación, el backend genera un token jwt que luego se envía a través de una cookie con el atributo HttpOnly de vuelta al frontend. Sin embargo, después de la autenticación, cada solicitud posterior al backend debe enviar el token para asegurar que el usuario esté conectado.

    El problema enfrentado es que cuando se despliega en Vercel y Heroku, ¡el navegador simplemente se niega a guardar la cookie HttpOnly! El token jwt aparece en el encabezado de respuesta después de enviar la solicitud de autenticación, pero no se guarda en el navegador. El desarrollador ha intentado cambiar los parámetros de la cookie, pero aún no funciona. CORS está configurado correctamente en el backend, junto con el módulo cookie-parser.

    El código para establecer la cookie HttpOnly es el siguiente:

    const authenticate = async (req, res, next) => {
      userService
        .authenticate(req)
        .then((user) => {
          const { token, ...userInfo } = user;
          res
            .setHeader(
              "Set-Cookie",
              cookie.serialize("token", token, {
                httpOnly: true,
                secure: process.env.NODE_ENV !== "development",
                maxAge: 60 * 60 * 24,
                sameSite: "none",
                path: "/",
              })
            )
            .status(200)
            .json(userInfo);
        })
        .catch(next);
    };
    

    La configuración de CORS en el backend es la siguiente:

    const cors = require("cors");
    const cookieParser = require("cookie-parser");
    
    app.use(
      cors({
        origin: "<client_url>",
        credentials: true,
      })
    );
    
    app.use(cookieParser());
    

    Solución

    El problema puede deberse al hecho de que la cookie HttpOnly debe establecerse con el valor del atributo SameSite como “none” y el valor del atributo Secure como true. Esto se debe a que el frontend está desplegado en Vercel que utiliza HTTPS pero el backend está desplegado en Heroku que utiliza HTTP.

    Cambiar el valor del atributo secure a false en el método de serialización de la cookie puede resolver el problema:

    .setHeader(
      "Set-Cookie",
      cookie.serialize("token", token, {
        httpOnly: true,
        secure: false,
        maxAge: 60 * 60 * 24,
        sameSite: "none",
        path: "/",
      })
    )
    

    Otra solución podría ser utilizar un servidor proxy entre el frontend y el backend para manejar solicitudes HTTPS y eliminar la necesidad de establecer el valor del atributo secure como false.

    Es importante tener en cuenta que establecer el valor del atributo SameSite como “none” y el valor del atributo Secure como true es una medida de seguridad necesaria que ayuda a proteger contra ataques de falsificación de solicitudes entre sitios (CSRF).

Comments are closed.