Search code examples
node.jsexpresscookiesaxiosvercel

Cookies aren't sent over Vercel


Site works great when backend and frontend are deployed locally (on two different ports) but cookies won't send when I run it on Vercel. I even tried running the front-end locally using the back-end that I deployed on Vercel and the request still didn't contain cookies.

This is what the request looks like using the local backend: enter image description here

And with the Vercel-deployed backend: enter image description here

My vercel.json file looks like this:

{
  "version": 2,
  "builds": [
    {
      "src": "*.js",
      "use": "@vercel/node"
    }
  ],
  "routes": [
    {
      "src": "/(.*)",
      "dest": "/",
      "methods": ["GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS"],
      "headers": {
        "Access-Control-Allow-Credentials": "true",
        "Access-Control-Allow-Origin": "http://localhost:3000",
        "Access-Control-Allow-Methods": "GET,OPTIONS,PATCH,DELETE,POST,PUT",
        "Access-Control-Allow-Headers": "*"
      }
    }
  ]
}

And I've configured axios to use credentials and set credentials to true in the Express index.js file. And, set-cookie works:

enter image description here

Would appreciate any help.

I've tried changing the headers a bunch and no combination seems to work.


Solution

  • Please see below a minimal code example showing a cookie passing through a request-response cycle. This example has been deployed in Vercel and it works there. The output shown below is taken from a deployment preview. Please see if it is useful to check with your code to find out any differences in the setup.

    Please also note that this example uses an HTML page as its frontend. It is being served from the same express server wherein the API is also hosted. Therefore there is no CORS involved in it.

    Note:

    Initially I tried to create another example with a CORS scenario. However, I could not make it deployed successfully in Vercel as its CORS setup did not match.

    index.js

    const express = require('express');
    const cookieParser = require('cookie-parser');
    
    const app = express();
    
    app.use(express.static('public'));
    
    app.use(cookieParser());
    
    app.get('/cookie', (req, res) => {
      let response;
    
      if (req.cookies?.somecookie) {
        response = 'Same cookie: A cookie received and the same sent to client';
      } else {
        res.cookie('somecookie', 'cookie text');
        response = 'New cookie: A new cookie created and sent to the client';
      }
    
      res.send(response);
    });
    
    app.listen(4000, () => {
      console.log(`L@4000`);
    });
    
    module.exports = app;
    

    Index.html

    <!DOCTYPE html>
    <html>
      <head>
        Cookie tests header
      </head>
      <body>
        <br />
        <br />
        Cookie tests body
        <br />
        <br />
        <p></p>
      </body>
      <script>
        const p = document.querySelector('p');
    
        fetch('/cookie', {
          method: 'GET',
        })
          .then((response) => {
            if (!response.ok) {
              p.textContent = 'Error occured';
            }
            return response.text();
          })
          .then((data) => {
            p.textContent = data;
          });
      </script>
    </html>
    

    vercel.json

    { "version": 2, "rewrites": [{ "source": "/(.*)", "destination": "/api" }] }
    

    Test results:

    1. On loading the site, the API creates a new cookie as shown in the browser screenshot below.

    enter image description here

    1. On refreshing the site, the API sends the same cookie back, which shows that the same cookie passes through a request-response cycle. enter image description here