简体   繁体   中英

Error: Can't set headers after they are sent when return jwt.verify

I want to make authentication depending features on the controller, so I made isAuthorized function like this:

const isAuthorized = (req) => {
  const token = req.cookies['jwt'];
  const sign = process.env.JWT_SECRET_KEY;

  return jwt.verify(token, sign, function(err, decoded) {
    console.log(decoded);
    if (err || !decoded) {
      console.log('invalid token');
      return false;
    } else if (decoded && (!decoded.access || decoded.access == 'unauthenticated')) {
      console.log('unauthenticated token');
      return false;
    } else if (decoded && decoded.access == 'authenticated') {
      console.log('valid token');
      return true;
    } else {
      console.log('something suspicious');
      return false;
    }
  });
};

usage:

const viewLogin = (req, res, next) => {
  if (isAuthorized(req)) {
    res.send('Already Logged In');
  }
  res.render('login');
};

It works exactly what I want but I got Error on a terminal.

GET /auth/login 200 8.810 ms - 17
Error: Can't set headers after they are sent.
    at SendStream.headersAlreadySent (/Users/james/Documents/Workspace/Centell/Project/weaver/node_modules/send/index.js:390:13)
    at SendStream.send (/Users/james/Documents/Workspace/Centell/Project/weaver/node_modules/send/index.js:618:10)
    at onstat (/Users/james/Documents/Workspace/Centell/Project/weaver/node_modules/send/index.js:730:10)
    at FSReqCallback.oncomplete (fs.js:159:5)

I tried to:

  • Defined the token from the outside( viewLogin ) and send it as a parameter( isAuthrized(token) ).
  • Use async/await pattern. ( await usAuthrized(req) )
  • Separate the result variable in isAuthorized .
const isAuthorized = req => {
  const token = req.cookies['jwt'];
  const sign = process.env.JWT_SECRET_KEY;
  let result;

  return jwt.verify(token, sign, function(err, decoded) {
    console.log(decoded);
    if (err || !decoded) {
      console.log('invalid token');
      result = false;
    } else if (decoded && (!decoded.access || decoded.access == 'unauthenticated')) {
      console.log('unauthenticated token');
      result = false;
    } else if (decoded && decoded.access == 'authenticated') {
      console.log('valid token');
      result = true;
    } else {
      console.log('something suspicious');
      result = false;
    }
  });

  return result;
};


but these are doesn't works.

How to fix this error?

Change the code as below :

const viewLogin = (req, res, next) => {
  if (isAuthorized(req)) {
    res.send('Already Logged In');
  } else {
    res.render('login');
  }
};

OR

const viewLogin = (req, res, next) => {
  if (isAuthorized(req)) {
    return res.send('Already Logged In');
  }
  res.render('login');
};

For an explanation why the original is not working. Since the response has already been sent using res.send, you will not be able to also use res.render. In order to prevent the res.render from executing, you will need to either return the res.send or use an if/else statement as shown in the other answer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM