How to fix "TypeError: Cannot read property 'body' of undefined' in an expressjs REST API"

Viewed 4950

I'm setting up a REST API using Express, I ended up defining some endpoints and methods thats works, when suddenly appears an error: "TypeError : Cannot read property 'body' of undefined"

I'm fairly new to JS and i'm trying to build a webapp using mongodb, express and react.

I've been following some guides (this one in particular because it also implements JWT : https://www.toptal.com/nodejs/secure-rest-api-in-nodejs)

I have managed to build all the users methods for basic CRUD operations and have exposed them. Everything works fine, then I tried to add the Auth process with middlewares, and the error happened.

I looked for the answer, most commonly the error was due to body-parser being called after the routes. But in my case, I call the auth route just before the user route which works fine.

Here is my git repo for more details : https://github.com/pidanou/btb_api

const config = require("./config/env.config");

const express = require("express");
const bodyParser = require("body-parser");
const app = express();

const authRouter = require("./routes/auth.routes");
const userRouter = require("./routes/users.routes");

app.use(function(req,res,next){
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Credentials', 'true');
    res.header('Access-Control-Allow-Methods', 
'GET,HEAD,PUT,PATCH,POST,DELETE');
    res.header('Access-Control-Expose-Headers', 'Content-Length');
    res.header('Access-Control-Allow-Headers', 'Accept, Authorization, 
Content-Type, X-Requested-With, Range');
    if (req.method === 'OPTIONS') {
        return res.send(200);
    } else {
        return next();
    }
});

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

authRouter.authRoutesConfig(app);
userRouter.userRoutesConfig(app);

app.listen(config.port, () => console.log(`Listening on port 
${config.port}`));

Code for the authRoute:

const verifyUserMiddle = require("../middlewares/verify.user.middle");
const authController = require("../controllers/auth.controller");

exports.authRoutesConfig = function (app) {

    app.post('/auth', [
        verifyUserMiddle.hasAuthValidFields(),
        verifyUserMiddle.isPasswordAndUserMatch(),
        authController.login()
    ])

}

Code for the controller:

const jwtSecret = require('../config/env.config').jwt_secret,
    jwt = require("jsonwebtoken");
const cyrpto = require("crypto");

exports.login = (req, res) => {

    try {
        let refreshId = req.body.userId + jwtSecret;
        let salt = crypto.randomBytes(16).toString("base64");
        let hash = cyrpto.createHmac("sha512", 
salt).update(refreshId).digest("base64");
        req.body.refreshKey = salt;
        let token = jwt.sign(req.body, jwtSecret);
        let b = new Buffer(hash);
        let refresh_token = b.toString("base64");
        res.status(201).send({accessToken: token, refresh_token: 
refresh_token});
    }catch(err){
        res.status(500).send({errors: err});
    }

} 

Since the user part worked fine, I thought the auth would too, but it didn't. It seems that the middleware is called before the body-parser. The error happens first in the middleware.

1 Answers

It's not a body-parser issue here - it works fine. As you can see your exports.login = (req, res) => {...} has req and res parameters, but how are they being received?

With having parantheses() in your authController.login() you prevented that, and as long as they're present, your app will crash and give such error.

So change to this:

  app.post('/auth', [
        (your code),
        authController.login
    ])  

Without parentheses.

Related