title: HttpOnly cookies are not sent with request to server
body: <p>I've created API in node express and I'm running it on port <code>:8000</code>, I am consuming APIs through simple CRA on port <code>:3000</code>. I've created registration and login with setting httpOnly cookie. Furthermore, I've put middleware to check each endpoint in order to verify if it has that token.
  When I test through Thunder/Postman everything works, after logging in I get the cookie in response, I set that cookie as auth token and make request to get data and I get the data.</p>
  <p>When I log in through the React Frontend it succeeds and I can see in network tab that I have received the cookie in response. But when I make a request to protected endpoint, the request does not have a cookie in it (I log incoming requests on server and compare ones made with Thunder/Postman client and via app in Browser).</p>
  <p>I use axios, and I've put <code>{withCredentials: true}</code> it doesn't work. I've used <code>withAxios</code> hook and it doesn't work either.</p>
  <p>SERVER</p>
  <p>index.js</p>
  <pre><code>...
  const app = express()
  app.use(cors({
      credentials: true,
      origin: 'http://localhost:3000',
  }));
  ...
  </code></pre>
  <p>controllers/User.js</p>
  <pre><code>...
  const loginUser = async(req, res) =&gt; {
      const body = req.body
      const user = await User.findOne({ email: body.email })
          if(user) {
          const token = generateToken(user)
          const userObject = {
              userId: user._id,
              userEmail: user.email,
              userRole: user.role
          }
          const validPassword = await bcrypt.compare(body.password, user.password)
          if(validPassword) {
              res.set('Access-Control-Allow-Origin', req.headers.origin);
              res.set('Access-Control-Allow-Credentials', 'true');
              res.set(
                  'Access-Control-Expose-Headers',
                  'date, etag, access-control-allow-origin, access-control-allow-credentials'
              )
              res.cookie('auth-token', token, {
              httpOnly: true,
              sameSite: 'strict'
              })
              res.status(200).json(userObject)
          } else {
              res.status(400).json({ error: &quot;Invalid password&quot; })
          }
      } else {
          res.status(401).json({ error: &quot;User doesn't exist&quot; })
      }
  }
  ...
  </code></pre>
  <p>middleware.js</p>
  <pre><code>...
  exports.verify = (req, res, next) =&gt; {
      const token = req.headers.authorization
      if(!token) res.status(403).json({ error: &quot;please provide a token&quot; })
      else {
          jwt.verify(token.split(&quot; &quot;)[1], tokenSecret, (err, value) =&gt; {
              if(err) res.status(500).json({error: &quot;failed to authenticate token&quot;})
              req.user = value.data
              next()
           })
      }
  }
  ...
  </code></pre>
  <p>router.js</p>
  <pre><code>...
  router.get('/bills', middleware.verify, getBills)
  
  router.post('/login', loginUser)
  ...
  </code></pre>
  <p>CLIENT</p>
  <p>src/components/LoginComponent.js</p>
  <pre><code>...
  const loginUser = (e) =&gt; {
          setLoading(true)
          e.preventDefault()
          let payload = {email: email, password: password}
          axios.post('http://localhost:8000/login', payload).then(res =&gt; res.status === 200 
          ? (setLoading(false), navigate('/listbills')) : navigate('/register'))
      }
  ...
  </code></pre>
  <p>src/components/ListBills.js</p>
  <pre><code>...
  useEffect(() =&gt; {
          fetch('http://localhost:8000/bills', {
              method: 'get',
              headers: {'Content-Type': 'application/json'}, 
              credentials: 'include',
          })
              .then(response =&gt; {console.log(response)}).catch(err =&gt; console.log(err));
      }, [])
  ...
  </code></pre>
  <p>I've also tried:</p>
  <pre><code>axios.get('http://localhost:8000/bills',{withCredentials: true})
    .then((data) =&gt; console.log(data))
    .then((result) =&gt; console.log(result))
    .catch((err) =&gt; console.log('[Control Error ] ', err))
      }
  </code></pre>
  <p>and</p>
  <pre><code>const [{ data, loading, error }, refetch] = useAxios(
    'http://localhost:8000/bills',{
    withCredentials: true,
    headers: {'Access-Control-Allow-Origin': '*', 'Content-Type': 'application/json'
  }})
  </code></pre>
  <p>Console.log error:</p>
  <p><a href="https://i.stack.imgur.com/rODJe.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/rODJe.png" alt="enter image description here" /></a></p>
  <p>After I login I get this in Network tab:</p>
  <p><a href="https://i.stack.imgur.com/lPrjG.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/lPrjG.png" alt="enter image description here" /></a></p>
  <p><a href="https://i.stack.imgur.com/0tu1Z.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/0tu1Z.png" alt="enter image description here" /></a></p>
  <p>However when I want to access the list:</p>
  <p><a href="https://i.stack.imgur.com/q67vP.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/q67vP.png" alt="enter image description here" /></a></p>
  <p><a href="https://i.stack.imgur.com/30n0E.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/30n0E.png" alt="enter image description here" /></a></p>
  <p>=== UPDATE ===</p>
  <p>So the cause of the issue is not having the httpOnly cookie passed in the request header. This is the log of the middleware I am using:</p>
  <pre><code>token undefined
  req headers auth undefined
  req headers {
    host: 'localhost:8000',
    connection: 'keep-alive',
    'sec-ch-ua': '&quot; Not;A Brand&quot;;v=&quot;99&quot;, &quot;Google Chrome&quot;;v=&quot;97&quot;, &quot;Chromium&quot;;v=&quot;97&quot;',
    'sec-ch-ua-mobile': '?0',
    'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36',
    'sec-ch-ua-platform': '&quot;macOS&quot;',
    'content-type': 'application/json',
    accept: '*/*',
    origin: 'http://localhost:3000',
    'sec-fetch-site': 'same-site',
    'sec-fetch-mode': 'cors',
    'sec-fetch-dest': 'empty',
    referer: 'http://localhost:3000/',
    'accept-encoding': 'gzip, deflate, br',
    'accept-language': 'en-US,en;q=0.9,hr;q=0.8,sr;q=0.7,bs;q=0.6,de;q=0.5,fr;q=0.4,it;q=0.3'
  }
  </code></pre>
  <p>token is read from <code>headers.authorization</code> but from the log of the <code>headers</code> it doesn't exist so my requests fail to be authorized.</p>
  <p>Still not working.</p>