How to add JWT and field verification with ExpressJS and multer

Viewed 307

I have a form that needs multipart/form-data because there is a file field in that form.

I am using ExpressJS, and I use multer to handle multipart/formdata.

Now I also need to verify the fields and the JWT in the header.

In my app I use middlewares for application/JSON type and do this like this:

app.delete("/ticket/:ticketId", [
    authValidation.validJWTNeeded,
    authValidation.verifyIfNotLoggedOut,
    authPermission.hasPermissionOrIsSameUser(staffRole),
    ticketController.deleteById
]);

In every middleware I pass arguments (req, res, next) and return next when needed, and i works fine.

I didn't manage to do it with multer without sending the file first. In documentation they will do something like this, which is not what i want because the file is already sent :

app.post("/route",
    multer.upload.single("avatar"),
    function (req, res, next) {
    // req.file is the `avatar` file
    // req.body will hold the text fields, if there were any
    })
)

i tried doing things like this but it didn't work :

app.post("/ticket", [
    async (req, res, next) => {
    multer.upload.none();
    let jwt = //req.headers....... this is the jwt sent
    //req.body should have all the fields
    return next
    },
    authValidation.validJWTNeeded,               //Here i verify the JWT for auth
    authValidation.verifyIfNotLoggedOut,         //About the same here
    ticketController.verifyFields,               // /!\ I need to verify if fields are correct
    //function/middleware to upload using multer.upload.single("field"), 
    ticketController.insert                      // If everything above passed, then create the ticket and upload the file
]);

So my question is : how do I do all the validation using multer and data sent with multipart/formdata encryption?

Thanks!

1 Answers

So I figured a way around, It's a pretty dirty way imho but it works... I used the fileFilter of multer and added in it all the validation needed, included JWT verify, field validation etc. By doing something like this, if anybody has a more suited way to do this, please feel free to answer.

//verify the jwt here

function isLoggedIn(req) {
    if (req.headers['authorization']) {
        try {
            let authorization = req.headers['authorization'].split(' ');
            if (authorization[0] !== 'Bearer') {
                return false
            } else {
                if(jwt.verify(authorization[1], config.jwt_secret)){
                    return true
                }
            }
        } catch (err) {
            return false
        }
    } else {
        return false
    }
}


//verify fields here
function verifField (req) {
    console.log(req.body.title)
    let fieldList = {
        title : false,
        message : false,
        category : false,
        response : false
    };

    if(req.body.title && req.body.title.trim() !== ""){
        fieldList.title = true;
    }

    if(req.body.message && req.body.message.trim() !== ""){
        fieldList.message = true;
    }

    if(req.body.category && ticketModel.ticketModel.schema.path("category").enumValues.includes(req.body.category)){
        fieldList.category = true;
    }

    if(!req.body.response){
        fieldList.response = true;
    }

    return fieldList.title &&  fieldList.message && fieldList.category && fieldList.response
}

//mix them both here + verify type    
function isValid (req) {
    return isLoggedIn(req) && verifField(req) && file.mimetype.match(/jpe|jpeg|png|gif$i/)
}

//export everything here
module.exports = {
    upload : multer({
        storage : storage,
        fileFilter : (req, file, cb) => {
            cb(null, isValid(req))
        }
    })
} ;
Related