What are good strategies for role-based authorization in express.js? Especially with express-resource?
With Express-resource there are no handlers, so I think there are
I would say that it's hard to solve this in a clean manner using express-resource, since it doesn't allow for route-specific middleware (at least not in a clean way).
I would opt for a similar layout as an express-resource module, but route it with plain old express. Something like this:
// Resource
var forum = {
index: // ...
show: // ...
create: // ...
update: // ...
destroy: // ...
};
// Middleware
var requireRole = function(role) {
return function(req, res, next) {
if('user' in req.session && req.session.user.role === role)
next();
else
res.send(403);
}
};
// Routing
app.get('/forums', forum.index);
app.get('/forums/:id', forum.show);
app.post('/forums', requireRole('moderator'), forum.create); // Only moderators can create forums
app.delete('/forums/:id', requireRole('admin'), forum.destroy); // Only admins can delete forums
UPDATE: There have been ongoing discussions regarding route-specific middleware in express-resource, e.g. here. The prevailing view seems to be to have an array per action, e.g.:
var forums = {
index: [ requireRole('foo'), function(req, res, next) { ... } ]
};
You could take a look through the pull requests and see if there is anything you could use. I totally understand it, of course, if you don't feel comfortable with that. I'm pretty sure we will see something like this in express-resource in the future.
The only other solution I can think of is along the lines of Jan Jongboom's answer, which would be to mount the resources with express-resource, but have middleware attached "outside" of that, something like:
app.delete('*', requireRole('admin')); // Only admins are allowed to delete anything
app.put('/forums/*', requireRole('moderator')); // Only moderators are allowed to update forums
But I regret that this leaks URLs all over the place.