Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express: call a middleware from another middleware

I'm new to Express 4 and i'm wondering something about how to implement this thing: I'm using jwt to authenticate the consumer of my API, to do that i have a pretty simple middleware to check the validity of the jwt token:

var requireValidToken = function(req, res, next) {
  var token = req.body.token || req.query.token || req.headers['x-access-token'];
  if (token) {
    try {
      var decoded = jwt.verify(token, req.app.get('superSecret'));
    } catch(err) {
      return res.json({ success: false, message: 'Failed to authenticate token.' });  
    }
    req.user = decoded.user;
    next();
  } else {
    return res.status(403).send({ 
        success: false, 
        message: 'No token provided.' 
    });
  }
};

This is working pretty well, but now, i want to extend this to be able to check the role of the user:

 router.get('/anAdminRoute', requireRole('ROLE_ADMIN'), function (req, res, next) {
      // some code...
 });

So i added a middleware for this:

var requireRole = function(role) {
  return function(req, res, next){
    // Dummy tests...
    if(req.user.role == roles.admin || req.user.role == role){
      next();
    } else {
      return res.status(403)({
        success: false,
        message: "Token valid, but you don't have the right permission to access this resource :)"
      });
    }
  }
}

But as this requireRole() function while obviously checks for a valid jwt token, i'm wondering how can i call my requireValidToken middleware within this function, and so not having to explicitly call it for each route i want to protect.

An easy solution would have been not to use requireValidToken as a middleware but i still want to be able to use it to protect certain routes

Edit: Solution

Chaining middlewares is a simple as that:

var middleware2 = function(param) {
  return function(req, res, next){
    middleware1(req, res, function(){
      // middleware2 code
    });
  }
}

If anybody interested, my final working solution to validate a user role:

var jwt = require('jsonwebtoken'),
  roles = require('../models/user').roles; 

// authentication middleware
// check if the given jwt token is valid
var requireValidToken = function(req, res, next) {
  var token = req.body.token || req.query.token || req.headers['x-access-token'];
  if (token) {
    try {
      var decoded = jwt.verify(token, req.app.get('superSecret'));
    } catch(err) {
      return res.json({ success: false, message: 'Failed to authenticate token.' });  
    }
    req.user = decoded.user;
    next();
  } else {
    return res.status(403).send({ 
        success: false, 
        message: 'No token provided.' 
    });
  }
};

var requireRole = function(role) {
  return function(req, res, next){
    requireValidToken(req, res, function(){
      if(req.user.role == roles.admin || req.user.role == role){
        next();
      } else {
        return res.status(403).send({
          success: false,
          message: "Token valid, but you don't have the right permission to access this resource :)"
        });
      }
    });
  }
}

module.exports = {
  requireValidToken: requireValidToken,
  requireRole: requireRole
}
like image 993
hexxxxx Avatar asked Dec 26 '15 04:12

hexxxxx


1 Answers

Completely misread your question. If you want to call requireValidToken for certain situations, you can pass along the req and res objects to the middleware function, along with an anonymous callback. How you get the middleware function largely depends on your application architecture so I'll assume I have the requireValidToken within my context:

var requireRole = function(role) {
  return function(req, res, next){
    // Dummy tests...

    requireValidToken(req, res, function () {
      if(req.user.role == roles.admin || req.user.role == role){
        next();
      } else {
        return res.status(403)({
          success: false,
          message: "Token valid, but you don't have the right permission to access this resource :)"
        });
      }
    });
  }
};
like image 59
Quy Avatar answered Nov 16 '22 13:11

Quy