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

2.6K
Visualizações
Cross-Domain Session Cookie (Express API on Heroku + React App on Netlify)

I have a React App making calls to an API in node.js/Express.

Frontend is deployed in Netlify (https), Backend deployed on Heroku (https).

My problem:

  • Everything working in dev environment (localhost)
  • In production (Netlify/Heroku), the api calls to register and login seem to work but the session cookie is not stored in the browser. Because of that, any other calls to protected routes in the API fail (because I don't receive the user credentials).

             cross-domain authentication cookie react express




Talking is cheap, show me the code....

Backend (Express API):

  • I'm using passport (local strategy), express-session, cors.

App.js

require('./configs/passport');

// ...

const app = express();

// trust proxy (https://stackoverflow.com/questions/64958647/express-not-sending-cross-domain-cookies)
app.set("trust proxy", 1); 

app.use(
  session({
    secret: process.env.SESSION_SECRET,
    cookie: {
      sameSite: process.env.NODE_ENV === "production" ? 'none' : 'lax',
      maxAge: 60000000,
      secure: process.env.NODE_ENV === "production",
    },
    resave: true,
    saveUninitialized: false,
    ttl: 60 * 60 * 24 * 30
  })
);

app.use(passport.initialize());
app.use(passport.session());

// ...


app.use(
  cors({
    credentials: true,
    origin: [process.env.FRONTEND_APP_URL]
  })
);

//...

app.use('/api', require('./routes/auth-routes'));
app.use('/api', require('./routes/item-routes'));


CRUD endpoint (ex. item-routes.js):

// Create new item
router.post("/items", (req, res, next) => {
    Item.create({
        title: req.body.title,
        description: req.body.description,
        owner: req.user._id // <-- AT THIS POINT, req.user is UNDEFINED
    })
    .then(
        // ...
    );
});

Frontend (React App):

  • Using Axios with the option "withCredentials" set to true...

User registration and login:

class AuthService {
  constructor() {
    let service = axios.create({
      baseURL: process.env.REACT_APP_API_URL,
      withCredentials: true
    });
    this.service = service;
  }
  
  signup = (username, password) => {
    return this.service.post('/signup', {username, password})
    .then(response => response.data)
  }

  login = (username, password) => {
    return this.service.post('/login', {username, password})
    .then(response => response.data)
  }
   
  //...
}

Creating a new item...:

    axios.post(`${process.env.REACT_APP_API_URL}/items`, {
        title: this.state.title,
        description: this.state.description,
    }, {withCredentials:true})
    .then( (res) => {
        // ...
    });
over 4 years ago · Santiago Trujillo
1 Respostas
Responde à pergunta

0

Short answer:

It wasn't working as expected because I was testing on Chrome Incognito and, by default, Chrome blocks third party cookies in Incognito mode (more details).

Below is a list with some things to check if you're having a similar issue ;)



Checklist

In case it helps, here's a checklist with different things that you main need ;)

  • (Backend) Add "trust proxy" option

If you're deploying on Heroku, add the following line (you can add it before your session settings).

app.set("trust proxy", 1);

  • (Backend) Check your session settings

In particular, check the option sameSite and secure (more details here).

The code below will set sameSite: 'none' and secure: true in production:

app.use(
  session({
    secret: process.env.SESSION_SECRET || 'Super Secret (change it)',
    resave: true,
    saveUninitialized: false,
    cookie: {
      sameSite: process.env.NODE_ENV === "production" ? 'none' : 'lax', // must be 'none' to enable cross-site delivery
      secure: process.env.NODE_ENV === "production", // must be true if sameSite='none'
    }
  })
);
  • (Backend) CORS config
app.use(
  cors({
    credentials: true,
    origin: [process.env.FRONTEND_APP_URL]
  })
);
  • (Backend) Environment Variables

Setup the environment variables in Heroku. For example:

FRONTEND_APP_URL = https://my-project.netlify.app

IMPORTANT: For the CORS URL, avoid a trailing slash at the end. The following may not work:

FRONTEND_APP_URL = https://my-project.netlify.app/ --> avoid this trailing slash!
  • (Frontend) Send credentials

Make sure you're sending credentials in your API calls (you need to do that for all calls you make to the API, including the call for user login).

If you're using axios, you can do use withCredentials option. For example:

    axios.post(`${process.env.REACT_APP_BACKEND_API_URL}/items`, {
        title: this.state.title,
        description: this.state.description,
    }, {withCredentials:true})
    .then( (res) => {
        // ...
    });
  • (Browser) Check the configuration for third-party cookies

For testing, you probably want to make sure you're using the default configuration provided by each browser.

For example, as of 2021, Chrome blocks third-party cookies in Incognito mode (but not in "normal" mode), so you probably want to have something like this:

enter image description here

  • ...and deal with browser restrictions...:

Finally, keep in mind that each browser has a different policy for third party cookies and, in general, those restrictions are expected to increase in the coming years.

For example, Chrome is expected to block third-party cookies at some point in 2023 (source).

If your App needs to bypass those restrictions, here are some options:

  • Implement Backend & Frontend under the same domain

  • Implement Backend & Frontend under subdomains of the same domain (example, example.com & api.example.com)

  • Have your Backend API under a proxy (if you're using Netlify, you can easily setup a proxy using a _redirects file)

over 4 years ago · Santiago Trujillo 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