Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JWT Token and Multer for File Uploads (Node)

I need a little help figuring out how to get this working -- I've tested and have working JWT authentication and SSL on my '/user' routes. I'm trying to safely allow the user to upload an audio file, also using the JWT and SSL route.

The authentication middleware works, and multer works to let me upload files when I comment out the authentication middleware. However, when I leave the middleware in, the uploaded file is created on my system, but the file fails to upload properly and I get a 404 error.

Thanks for any help!

server.js (main file)

var express     = require('express')
, app           = express()
, passport      = require('passport')
, uploads       = require('./config/uploads').uploads
, user_routes   = require('./routes/user')
, basic_routes  = require('./routes/basic')
, jwt           = require('jwt-simple');

// get our request parameters
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());


// Use the passport package in our application
app.use(passport.initialize());
require('./config/passport')(passport);

//double check we have an ssl connection
function ensureSec(req, res, next) {
    if (req.headers['x-forwarded-proto'] == 'https') {
        return next();
    } else {
         console.log('NOT SSL PROTECTED! rejected connection.');
         res.redirect('https://' + req.headers.host + req.path);
    }
}

app.use(ensureSec);


//authenticate all user routes with passport middleware, decode JWT to see
//which user it is and pass it to following routes as req.user
app.use('/user', passport.authenticate('jwt', {session:false}), user_routes.middleware);

//store info on site usage- log with ID if userRoute
app.use('/', basic_routes.engagementMiddleware);

// bundle our user routes
var userRoutes = express.Router();
app.use('/user', userRoutes);


userRoutes.post('/upload', uploads:q, function(req,res){
    res.status(204).end("File uploaded.");
});

// Start the server
app.listen(port);

routes/basic_routes.js (tracks engagement middleware)

var db   = require('../config/database')
, jwt    = require('jwt-simple')
, getIP  = require('ipware')().get_ip
, secret = require('../config/secret').secret;


exports.engagementMiddleware = function(req, res, next){

    if (typeof(req.user) == 'undefined') req.user = {};

    var postData = {};
    var ip = getIP(req).clientIp;
    var fullUrl = req.protocol + '://' + req.get('host') + req.originalUrl;

    if (req.method=="POST") postData = req.body;

    var newEngagement = new db.engagementModel({
    user_id: req.user._id,
    ipAddress: ip,
    url: fullUrl,
    action: req.method,
    postData: postData
    });
    //log the engagement
    newEngagement.save(function(err) {
    if (err) {
        console.log('ERROR: engagement middleware db write failed');
        next();
    }
    console.log('LOG: user ' + req.user._id +' from ipAddress: ' + ip + ': ' + req.method + ' ' + fullUrl);
    next();
    });

    next();
}

config/passport.js (passport authentication middleware)

var JwtStrategy = require('passport-jwt').Strategy;

// load up the user model
var db = require('../config/database'); // get db config file
var secret = require('../config/secret').secret;

module.exports = function(passport) {
var opts = {};
opts.secretOrKey = secret;
passport.use(new JwtStrategy(opts, function(jwt_payload, done) {
    db.userModel.findOne({id: jwt_payload.id}, function(err, user) {
        if (err) {
            return done(err, false);
        }
        if (user) {
            done(null, user);
        } else {
            done(null, false);
        }
    });
}));
};

routes/user_routes.js (user route middleware, user add to header)

var jwt = require('jwt-simple');
var db    = require('../config/database');
var secret = require('../config/secret').secret;

//expose decoded userModel entry to further routes at req.user
exports.middleware = function(req, res, next){

var token = getToken(req.headers);
if (token) req.user = jwt.decode(token, secret);
else res.json({success: false, msg: 'unable to decode token'});

//should be unnecessary, double checking- after token verification against db
db.userModel.findOne({email: req.user.email}, function (err, user) {
    if( err || !user ) {
        console.log('something has gone horribly wrong. Token good, no user in db or access to db.');
        return res.status(403).send({success: false, msg: 'unable to find user in db'});
    }
});
//end unnecessary bit

next();
}


//helper function
getToken = function (headers) {
if (headers && headers.authorization) {

    var parted = headers.authorization.split(' ');
    if (parted.length === 2) return parted[1];
    else return null;

} else { return null; }
};

config/uploads.js (finally where we try to upload)

var moment = require('moment');
var multer = require('multer');
var jwt = require('jwt-simple');

var uploadFile = multer({dest: "audioUploads/"}).any();

var storage = multer.diskStorage({
    destination: function (req, file, cb) {
        cb(null, 'audioUploads/')
    },
    filename: function (req, file, cb) {
        cb(null, req.user._id + '_' + moment().format('MMDDYY[_]HHmm') + '.wav')
    }
});

exports.uploads = multer({storage:storage}).any();
like image 407
dramsay Avatar asked Nov 08 '22 21:11

dramsay


1 Answers

in your server.js do this:

const authWare = passport.authenticate('jwt', {session:false});

userRoutes.post('/upload', authWare, uploads:q, function(req,res){
    res.status(204).end("File uploaded.");
});

works for me!

like image 121
Zeitrebell Avatar answered Nov 15 '22 05:11

Zeitrebell