1

I have multiple route pages. Let's call 'em parent route (index.js) and child routes (child1.js, child2.js). All these pages have multiple routes specified in them. Some of them need to be protected and some are better unprotected.

With the help of JSON web tokens and jsonwebtoken package, I created a middleware which checks whether a user can access a particular route. User can access them only if they have passed a valid json token. This is for protected routes. For unprotected routes, there is no need for such a thing.

I'm keeping middleware in a separate page and I'm exporting it to routes page using module.exports and then injecting it into protected routes.

But it's not working. I tried accessing the protected routes using POSTman client but the request is never being sent. Loader spinner shows.

This is my code:

auth-middleware.js

module.exports = function () {
    return function (req, res, next) {
        // check header or url parameters or post parameters for token
        var token = req.body.token || req.query.token || req.headers['x-access-token'];

        // decode token
        if (token) {
            // verifies secret and checks exp
            jwt.verify(token, config.secret, function (err, decoded) {
                if (err) {
                    return res.json({ success: false, message: 'Failed to authenticate token.' });
                } else {
                    // if everything is good, save to request for use in other routes
                    req.decoded = decoded;
                    next();
                }
            });
        }
        else {
            // if there is no token
            // return an error
            return res.status(403).send({
                success: false,
                message: 'No token provided.'
            });
        }
    }
}

My parent route: index.js

var router = require('express').Router();

var protected = require('./auth-middleware')();

var childRoute1 = require('./child1');
var childRoute2 = require('./child2');
router.use('/child1', childRoute1);
router.use('/child2', childRoute2);

//unprotected parent route
router.get('/', function (req, res, next) {
  res.json('Unprotected route 1!');
});

//unprotected parent route
router.get('/albums/what',protected, function (req, res, next) {
  res.json('album!');
});

router.route('/login').post(User.loginUser);

module.exports = router;

My Child Route 1: child1.js

var child1Router = require('express').Router();
var protected = require('./auth-middleware')();
var ChildC = require('../controllers/childController');

child1Router.route('/all',protected).get(ChildC.fetchAllChildData); //protected
child1Router.route('/my').get(ChildC.fetchMyChildData); //unprotected

module.exports = child1Router;

child2 is similar to child1. So I'm not including it.

UPDATE

I already included body parser in app.js file (main file)

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

var routes = require('./routes/index');
var port = process.env.PORT || 3000; //set our port

//configure body parser
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use('/api', routes);
app.use(function (req, res) {
  res.status(404).send({ url: req.originalUrl + ' not found' })
});

app.listen(port);
console.log('Magic happens on port ' + port);

module.exports = app;
Smokey
  • 1,857
  • 6
  • 33
  • 63
  • Where is your body-parser in index.js. How can you get the token from req.body or req.query without parsing the request.The body-parser must existed. – Vaibhav Patil Jul 13 '17 at 07:14
  • How are you sending the request in postman? As @VaibhavPatil points out, you don't show body-parser so `req.body.token` will never be there as it is only populated when you install middleware to parse the request body and put the results into `req.body`. body-parser is not needed for `req.query.token` or `req.headers['x-access-token']` as those are available in plain Express. – jfriend00 Jul 13 '17 at 07:33
  • @john Doe you didn't mount the router to the app. write this var app = express(); and at the end of index.js app.use("/", router); – Vaibhav Patil Jul 13 '17 at 07:39
  • @Vaibhav Patil I already included bodyparser in app.js file and mounted the route as well. please check the updated code. – Smokey Jul 13 '17 at 08:35
  • @JohnDoe When you import the middleware, you shouldn't execute it, just add it to the route – Akinjide Jul 13 '17 at 08:42

1 Answers1

1

You can export the middleware as an object with verify method, like so:

auth-middleware.js

module.exports = {
    verify: function (req, res, next) {
        // check header or url parameters or post parameters for token
        var token = req.body.token || req.query.token || req.headers['x-access-token'];

        // decode token
        if (token) {
            // verifies secret and checks exp
            jwt.verify(token, config.secret, function (err, decoded) {
                if (err) {
                    return res.json({ success: false, message: 'Failed to authenticate token.' });
                } else {
                    // if everything is good, save to request for use in other routes
                    req.decoded = decoded;
                    next();
                }
            });
        }
        else {
            // if there is no token
            // return an error
            return res.status(403).send({
                success: false,
                message: 'No token provided.'
            });
        }
    }
}

You can now require var authMiddleware = require('../auth-middleware');

index.js

var router = require('express').Router();
var authMiddleware = require('./auth-middleware');

var childRoute1 = require('./child1');
var childRoute2 = require('./child2');
router.use('/child1', childRoute1);
router.use('/child2', childRoute2);

// unprotected parent route
router.get('/', function (req, res, next) {
  res.json('Unprotected route 1!');
});

// protected parent route
router.get('/albums/what', authMiddleware.verify, function (req, res, next) {
  res.json('album!');
});

router.route('/login').post(User.loginUser);

module.exports = router;

Or you could put protected route under router.user, like so:

 router.use('/child1', childRoute1);
 router.use('/child2', childRoute2);

 // unprotected parent route
 router.get('/', function (req, res, next) {
   res.json('Unprotected route 1!');
 });
 router.route('/login').post(User.loginUser);

 // route middleware to verify token
 router.use(authMiddleware.verify);

 // protected parent route
 router.get('/albums/what', function (req, res, next) {
   res.json('album!');
 });
Akinjide
  • 2,723
  • 22
  • 28