Search code examples
node.jsexpressmiddleware

Express middleware protected and unprotected routes


I have some routes under /users that I want to require an authentication token and some that I do not. In order to achieve this I have done the following.

var protected = express.Router();
var unprotected = express.Router();

unprotected.post('/', function(req, res, next) { // A
   // no auth required
   next();
});

protected.get('/', function(req, res, next) { // B
   // auth required
   next();
});

module.exports = {
    protected: protected,
    unprotected: unprotected
};

And then I mount those routes in the following way.

var users = require('./routes/users');

app.use('/users', unprotected_middleware, users.unprotected); // C
app.use('/users', protected_middleware, users.protected); // D

app.use(resultHandler); // Middleware for sending the response (all routes) 
app.use(errorHandler);  // Middleware for handling errors (all routes)

When I make a POST to /users it runs the expected route, however when next() gets called the protected_middleware runs. This happens because it finds the next /users definition at the line marked with 'D'.

What is the recommended way to get around this?

For each resource I want the ability to have different middleware per route.

POST /users           (no auth)
GET /users            (requires auth)
DELETE /users/{id}    (requires auth and admin access)

Solution

  • You don't need two separate routers here, simply use the middlewares for protected and unprotected where needed (in the router get/post functions):

    users.js:

    var router = express.Router();
    
    router.post('/', unprotected_middleware, 
       function(req, res, next) { // A
         // no auth required
         next();
      }
    );
    
    router.get('/', protected_middleware, 
        function(req, res, next) { // B
          // auth required
          next();
        }
    );
    module.exports = router;
    

    and then:

    var users = require('./routes/users');
    
    app.use('/users', users);
    
    app.use(resultHandler); // Middleware for sending the response (all routes) 
    app.use(errorHandler);