Search code examples
node.jsreactjscookiesaxios

axios cannot send cookie with request even with withCredential: true


I already did the setup on server like this

app.use((req, res, next) => {
  res.header('Access-Control-Allow-Origin', 'http://localhost:3000');
  res.header(
    'Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept, Authorization,  X-PINGOTHER'
  );
  res.header('Access-Control-Allow-Credentials', true);
  res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS');
  next();
});

and the axios on client side (react) is like this

axios.defaults.withCredentials = true;
axios('http://127.0.0.1:3001/orders', {
  method: 'GET',
  withCredentials: true
}).then(res => {
    console.log(res);
}).catch(err => {
    console.log(err.response);
})

Everything works fine when I test with Postman and type directly to chrome. Any idea what's wrong with my code?


Solution

  • If you plan on using this mulitple times, then just create an axios config:

    client/src/utils/axiosConfig.js

    import axios from 'axios';
    
    const baseURL = process.env.NODE_ENV === "development"
      ? "http://localhost:3001/"
      : "http://example.com"
    
    const app = axios.create({
        baseURL,
        withCredentials: true
    })
    
    /* 
      The below is required if you want your API to return 
      server message errors. Otherwise, you'll just get 
      generic status errors.
    
      If you use the interceptor below, then make sure you 
      return an "err" (or whatever you decide to name it) message 
      from your express route: 
      
      res.status(404).json({ err: "You are not authorized to do that." })
    
    */
    app.interceptors.response.use(
      response => (response), 
      error => (Promise.reject(error.response.data.err))
    )
    
    export default app;
    

    client/src/actions/exampleAction.js

    import app from '../utils/axiosConfig';
    
    export const exampleAction = () => (
      app.get('orders') // this will be defined as baseURL + "orders" (http://localhost:3001/orders)
        .then(res => console.log(res))
        .catch(err => console.log(err))
    )
    

    Then for your API, instead of specifying CORS headers, you can simply use cors wherever you're defining your express middleware:

    const cors = require('cors');
    const origin = process.env.NODE_ENV === "development" 
      ? "http://localhost:3000" 
      : "http://example.com"
    
    app.use(
      cors({
        credentials: true,
        origin
      }),
    );