Search code examples
javascriptexpresscookiesaxios

Axios doesn't create a cookie even though set-cookie header is there?


Front-End: [Axios]

  const formSubmit = async (e) => {
    e.preventDefault()
    const formData = new FormData(e.target)
    const email = formData.get('email')
    const password = formData.get('password')
    try {
      const res = await axios.post('http://172.16.2.19:3001/api/v1/auth/login', {
        email,
        password,
      })
      console.log(res.data) // its okay, I can login if email & password are correct.
    } catch (error) {
      console.log(error)
    }
  }

Back-End [Nodejs ExpressJs]:

Inside App.js:

const cors = require('cors')
app.use(cors({ credentials: true }))

Inside Login.js (/auth/login endpoint):

// ... code, then... if email & password are correct:
// 3600000ms = 1hour
res.cookie('jwt', token, { httpOnly: true, expires: new Date(Date.now() + 3600000 })
res.status(200).json({
    status: 'success'
    token,
    data: userDoc,
})

Then, when I login in my browser:

enter image description here

I can login successfully, but no cookies will be created, see:

enter image description here

  • The front-end http service (react app) is running on http://172.16.2.19:3000
  • The back-end http service (expressjs) is running on http://172.16.2.19:3001
  • The axios requests I'm sending from the front-end are requesting: http://172.16.2.19:3001

So what's the problem?

The problem that no cookies are getting created in the browser is preventing me from continuing to design the front-end application, because if I wanted to request anything from my API, I have to be authenticated, all the routes on the API I made are protected, so if I wanted to request anything from the API, I will have to send my jwt token along with the request.

edit **:

here's the response from the /auth/login endpoint after successfully logging in:

enter image description here

  • I am using brave browser, the latest version.
  • I tried this on firefox, it has the same behavior.

enter image description here


Solution

  • let me save you time:

    For anyone having the same problem, all you have to do is

    change your backend code from:

    const cors = require('cors')
    app.use(cors({ credentials: true }))
    

    to

    app.use(cors({ credentials: true, origin: true }))
    

    and make sure you're using withCredentials: true on the front-end with every request (the login POST method and all the other requests that requires authentication)

    why?

    setting origin property to true is going to reflect the request origin, the origin property can be a string if you wanted to specify a particular domain, ex: http://localhost:3000. But if you have more than one client, setting this to true is a wise choise.

    and for those of you wondering about mobile devices in case of specifying a string for the origin field with one particular domain. This problem of cors only happens in browsers, any other client doesn't use that CORS policy.