mr.abdo
mr.abdo

Reputation: 485

Cookie is not set using express and passport

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.

Upvotes: 6

Views: 9403

Answers (1)

Asif Rahman
Asif Rahman

Reputation: 465

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"

Upvotes: 4

Related Questions