2

Full github repo https://github.com/suubcity/fso-blog-list/tree/bb3b8f623da4d9a5dcf87c2d82ccf3715dfbd3fb

When an invalid token is sent to this line of code...

const decodedToken = jwt.verify(req.token, process.env.SECRET);
            'TYPEOF:',

I want to handle it with the error handler below. The error handler works, I get the status code and json returned however my app still crashes. How can I prevent the crash?

middleware

const errorHandler = (err, request, res, next) => {
    logger.error(err.message);

    if (err.name === 'ValidationError') {
        return res.status(400).json({ error: err.message });
    } else if (err.name === 'JsonWebTokenError') {
        res.status(401).json({ error: 'invalid token' });
    }

    next(err);
};

error message

Connected to MongoDB
Server running on port 3001
invalid signature
POST /api/blogs 401 25 - 9.366 ms
JsonWebTokenError: invalid signature
    at /home/martyn/Documents/projects/fso-blog-list/node_modules/jsonwebtoken/verify.js:133:19
    at getSecret (/home/martyn/Documents/projects/fso-blog-list/node_modules/jsonwebtoken/verify.js:90:14)
    at Object.module.exports [as verify] (/home/martyn/Documents/projects/fso-blog-list/node_modules/jsonwebtoken/verify.js:94:10)
    at /home/martyn/Documents/projects/fso-blog-list/controllers/blogs.js:13:27
    at newFn (/home/martyn/Documents/projects/fso-blog-list/node_modules/express-async-errors/index.js:16:20)
    at Layer.handle [as handle_request] (/home/martyn/Documents/projects/fso-blog-list/node_modules/express/lib/router/layer.js:95:5)
    at next (/home/martyn/Documents/projects/fso-blog-list/node_modules/express/lib/router/route.js:137:13)
    at Route.dispatch (/home/martyn/Documents/projects/fso-blog-list/node_modules/express/lib/router/route.js:112:3)
    at newFn (/home/martyn/Documents/projects/fso-blog-list/node_modules/express-async-errors/index.js:16:20)
    at Layer.handle [as handle_request] (/home/martyn/Documents/projects/fso-blog-list/node_modules/express/lib/router/layer.js:95:5)
    at /home/martyn/Documents/projects/fso-blog-list/node_modules/express/lib/router/index.js:281:22
    at Function.process_params (/home/martyn/Documents/projects/fso-blog-list/node_modules/express/lib/router/index.js:335:12)
    at next (/home/martyn/Documents/projects/fso-blog-list/node_modules/express/lib/router/index.js:275:10)
    at Function.handle (/home/martyn/Documents/projects/fso-blog-list/node_modules/express/lib/router/index.js:174:3)
    at router (/home/martyn/Documents/projects/fso-blog-list/node_modules/express/lib/router/index.js:47:12)
    at newFn (/home/martyn/Documents/projects/fso-blog-list/node_modules/express-async-errors/index.js:16:20)
suubcity
  • 21
  • 2
  • This might help for the invalid signature...https://stackoverflow.com/questions/50774780/always-getting-invalid-signature-in-jwt-io...Otherwise the other option is to do the processing in the callback provided within JWT...custom error handling can be done within the callback. – Linus Oct 23 '21 at 21:08

1 Answers1

0

I've had the same problem while going through probably the same course.

So, I've got a problem with server stop/crash/death from any error coming from several libraries used. Jsonwebtoken, mongoose, bcryptjs all make the same problem - if they get unexpected data of any kind, they throw an error which stops the server. Looks like these problems must be handled by errorHandler middleware written in the course with (next) bringing the server to await next command/request But if jsonwebtoken gets no token after "Authorization: bearer ***" header or the token is malformed (hand-written nonsense token) or the token is expired, the server stops. It doesnt stop only if the token is valid.

If mongoose gets some (any) data that doesnt meet the requirements of validation written in the model, it throws an error which causes the server to stop.

If bcrypt gets no password to parse/verify/decrypt - it throws an error which causes the server to stop.

Then, /suddenly/, I've found that I missed adding library called express-async-error. The course stated this step clearly, that one must either wrap every call for "await" inside "async" function with try/catch block with "catch" - catching the error, or (!) install express-async-error library. So I've read through that 5 times until I understood that I've deleted all try/catch blocks and didn't install this library.

So, this solved all problems with mongoose and bcrypt, but jsonwebtoken still didn't want to stop crashing the server when there was no authorization header or null token.

Solution for me was to add another middleware that returned error before jwt.verify(req.token, process.env.SECRET).

const verifyToken = (request, response, next) => {
  const authorization = request.get('authorization')
  const token =
    authorization && authorization.toLowerCase().startsWith('bearer ')
      ? authorization.substring(7)
      : null

  if (!request.headers.authorization) {
    return response.status(401).json({ error: 'Authorization required' })
  }
  if (token === 'null') {
    return response.status(401).json({ error: 'token missing' })
  }
  const payload = jwt.verify(token, config.SECRET)
  if (!payload) {
    return response.status(401).json({ error: 'token missing or invalid' })
  }
  request.userId = payload.id
  request.token = token
  next()
}

P.S. errors from mongoose and bcryptjs were looking like totally the same, I mean they had the same structure before I added express-async-error library, that's why I mentioned them

  • Suubcity asked "How can I prevent the crash?" One way - to use middleware to prevent jwt from getting invalid token to handle with. Introduction, maybe, is too big and has no visible connections with the question, however, errors from jwt described in the question from Suubcity are looking the same as errors from other middleware without catching / handling. Actually, I googled error from mongoose and got on this page, not with error from jwt. – Mikhail Dyachenko Oct 25 '22 at 11:16
  • If I would see such answer when I've been googling to solve my problem, it would save me approximately 8 hours. Maybe it can help someone to save even more. If there is a better answer, I dont see it in other answers for this question. – Mikhail Dyachenko Oct 25 '22 at 11:42