Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

res.cookie not setting cookie in browser

I am currently trying to set up a Node/Express app with a React client to interact with it. I setup passport to handle authentication with JWT. When the user logs in, I validate the email/password. I then set the cookie:

res.cookie('jwt', token, { httpOnly: true, secure: false });

I see the token being passed back in the response header, but when I inspect my Chrome browser's cookie under Developer Tools > Application > Cookies, I see an empty cookie. What am I doing wrong and how do I send the jwt in the response header with subsequent requests?

server/App.js

const app = express()

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());

app.use(cookieParser());

app.use(function(req, res, next) {
  res.header("Access-Control-Allow-Origin", "*");
  res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
  next();
});

app.post('/login', (req, res) => {
  passport.authenticate('local', { session: false }, (error, user) => {
    if (error || !user) {
      res.status(400).json({ error });
    }

    // Construct JWT payload
    const payload = {
      email: user.email,
      expires: Date.now() + parseInt(process.env.JWT_EXPIRATION_MS),
    };

    // Assign payload to req.user
    req.login(payload, {session: false}, (error) => {
      if (error) {
        res.status(400).send({ error });
      }
      // Generate a signed JWT
      const token = jwt.sign(JSON.stringify(payload), process.env.JWT_SECRET);

      // Assign JWT to cookie
      res.cookie('jwt', token, { httpOnly: true, secure: false });
      res.status(200).send({ email: user.email });
    });
  })(req, res);
});

client/LoginModal.js

  handleLogin = async () => {
    const { name, email, password } = this.state

    try{
      const res = await axios.post('http://localhost:8080/login', {
        email: email,
        password: password,
      })

      if(res.status == 200){
        console.log("Logged in")
        console.log(res)
      }

    } catch (err) {
      console.log(err)
    }
  }

Edit: My current workaround is to send the token as part of the payload. My react client then grabs the token from the payload and stores it in the browser's cookie. Is there a way to avoid this workaround (see below for example)?

server

 res.status(200).send({ email: user.email, jwt: token });

client

  if(res.status == 200){
    cookies.set('jwt', res.data.jwt)
    cookies.set('email', res.data.email)
  }
like image 373
Huy Avatar asked Dec 14 '18 22:12

Huy


1 Answers

When making the axis.post() call, you'll have to pass {withCredentials: true, credentials: 'include'} as your second argument, only this way will your browser set the cookies.

like image 168
Jeremy Avatar answered Oct 19 '22 23:10

Jeremy