Cookie is not set using express and passport

Viewed 6289

I spent a long time trying figure it out why it's not working.

I'm implementing a login page using react. This page send the user and pass to backend (nodejs + express) using axios:

const login = useCallback(e => {
    e.preventDefault()
    fetch(process.env.REACT_APP_HOST + '/login', {
      method: 'POST',
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({
        username: e.target.elements.username.value,
        password: e.target.elements.password.value
      })
    })
      .then(response => {
        if (response.ok) {
          return response.json()
        } else if (response.status === 401) {
          throw new Error('Invalid user or pass.')
        } else {
          throw new Error('An error ocurred')
        }
       ...
      })

  }, [])

In backend, I have a route that receive those data and check on ldap system. So I generate a token using JWT and save it on token

const express = require('express'),
    passport = require('passport'),
    bodyParser = require('body-parser'),
    jwt = require('jsonwebtoken'),
    cors = require('cors')
    cookieParser = require('cookie-parser')
    LdapStrategy = require('passport-ldapauth');

let app = express();
app.use(cookieParser())
app.use(cors());

....

app.post('/login', function (req, res, next) {

        passport.authenticate('ldapauth', { session: false }, function (err, user, info) {

            const token = jwt.sign(user, env.authSecret)
            res.cookie('cookie_token', token) //it doesn't set the cookie

            if (err) {
                return next(err)
            }
            if (!user) {
                res.sendStatus(401)
            } else {
                return res.status(200).send({ firstName: user.givenName});
            }
        })(req, res, next);
    });

The problem is that the token is empty, it's not being set.

1 Answers

Couple of things. In your react fetch post method you need to add

withCredentials: true,

beside the httpheader.

 fetch(process.env.REACT_APP_HOST + '/login', {
  method: 'POST',
  withCredentials: true,
  credentials: 'include',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    username: e.target.elements.username.value,
    password: e.target.elements.password.value
  })
})

After that in your nodejs part you are using cors but validating all origin. Thats not going to work with credentials. You need to use cors like this to validate specific origin and also turn credentials to true-

app.use(cors({credentials: true, origin: 'http://localhost:4200'}));

after that you can send your cookie by

res.cookie('cookie_token', token, { maxAge: 900000 }) 

chrom application cookie view

This way the cookie will arrive and once the cookie is arrived in client side you can retrieve the cookie with document.cookie or with any other package like "js-cookie"

Related