REST express-resource and authorization - declarative authorization middleware?

848 views
Skip to first unread message

deitch

unread,
Jul 29, 2013, 1:27:21 PM7/29/13
to expre...@googlegroups.com
Question: is there benefit, for app.resource() style REST or in general, in having a declarative authorization middleware?

(regrets if this double-posted; it didn't appear to go through to Google Groups correctly the first time)

Express-resource is essentially a convenience function:

    app.resource('user',userHandler)

is just a much shorter form of

    app.get('/user',userHandler.index);
    app.get('/user/:user',userHandler.show);
    //etc.

The problem with app.resource() is that it doesn't give any route-specific middleware, which makes security constraints difficult. E.g. if I only want each person to view their own user, and only admins can list all users, nothing I can do in app.resource().

To solve this, I have the seed of a middleware that would let you do:

app.use(authorizer('./path/to/file.json'));
app.use(app.router);

The json config file looks like:

{
  rules:[
    // [verb,path,default,condition]
    ['GET','/user','deny','req.user && req.user.roles.admin === true'],
    ['GET','/user/:user','deny','req.user && req.user.roles.admin === true || req.user.id === :user'],
    // etc.
  ]
}

It gets more flexible than that, but is essentially declarative authorization for all paths.

1) Would people find this useful (with app.resource() REST or generally)?
2) With this middleware, you need to list out all verbs and routes all over again. Does this eliminate all the benefit of app.resource() in the first place?

greelgorke

unread,
Jul 29, 2013, 2:25:08 PM7/29/13
to expre...@googlegroups.com
1. look at passport module, it's basicaly your authorizer function done and done well.

2. you could take a look on mountable apps: https://vimeo.com/56166857 this could replace most of features of express-resource (not all), and is authorization friendly.

3. if you stick with express-resource, you can call passport authorize from your handler before processing any further. or you can implement your variant with declarative listing of routes and asigning validation rules there

deitch

unread,
Jul 29, 2013, 2:31:14 PM7/29/13
to expre...@googlegroups.com
1. I have looked at passport, looks like a much smoother version of the authentication side of cansec. But passport is authentication, not authorization. It will help keep track of a user, not if a user who is logged in has rights to perform a certain action.

2. I will definitely take a loo, thanks.

deitch

unread,
Jul 29, 2013, 2:38:42 PM7/29/13
to expre...@googlegroups.com
OK, I give. How does mountable apps replace express-resource?


On Monday, July 29, 2013 9:25:08 PM UTC+3, greelgorke wrote:

greelgorke

unread,
Jul 30, 2013, 7:34:35 AM7/30/13
to expre...@googlegroups.com
1. it does both: http://passportjs.org/guide/authorize/

on mountable apps: every app can be a single resource with it's own set of configurations including authorization. so instead of writing 

export.index = function()...

for express-resource, you write 

app.get('/', function(){...})

but as is said, it may replace some not all of it's functionality.

deitch

unread,
Jul 30, 2013, 3:08:27 PM7/30/13
to expre...@googlegroups.com
Nah, that's not authorization, it's authentication plus "make sure the user is logged in first", which is very basic binary authorization.

Real authorization is "this action is only allowed for user X; this action is only allowed for admins; this path is only allowed for the user whose id matches the creatorId field in the record we are retrieving plus admins; etc."

Mountable is interesting, but doesn't really do what I want. I like the app.resource('user') concept, looks like I will need to roll in proper authorization.

Jed Wood

unread,
Jul 31, 2013, 11:51:30 AM7/31/13
to expre...@googlegroups.com
You might want to check out express-resource-new. It's got a "before" block and I dig the way resources are nested.

-Jed

deitch

unread,
Jul 31, 2013, 1:30:04 PM7/31/13
to expre...@googlegroups.com
Heh, not bad at all. I hadn't seen this fork, and I had need for an even more automated controller and model structure for REST, so I rolled my own. Should npm publish it later this week / early next.

How would you embed authorization in express-resource-new?

Jed Wood

unread,
Jul 31, 2013, 1:42:30 PM7/31/13
to expre...@googlegroups.com
Oh I'm sure there are lots of ways, but here's what I've done.

- use Passport in whatever setup works.
- create a simple "auth" middleware function in your controller that checks for req.whatever from Passport, e.g.:

function auth(req, res, next) {
  if (req.user && (req.user.isAdmin || req.user.id == req.params.person)) {
    next();
  } else {
    res.send(401);
  }
}

- apply that auth middleware to whatever routes need it in the "before" block:

 options: {

    before: {
      show: [auth, load],
      index: superAdmin,
      edit: [auth, load],
      update: [auth, load],
      destroy: [auth, load]
    }
  }

-Jed


--
You received this message because you are subscribed to a topic in the Google Groups "Express" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/express-js/0KcH37KX2rw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to express-js+...@googlegroups.com.
To post to this group, send email to expre...@googlegroups.com.
Visit this group at http://groups.google.com/group/express-js.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

deitch

unread,
Jul 31, 2013, 2:02:44 PM7/31/13
to expre...@googlegroups.com
OK, that's pretty nifty. The 'before' option provides quite a bit of flexibility. Now that I understand it, it is very similar to what I had envisioned (and mostly built). 

deitch

unread,
Aug 5, 2013, 11:18:33 AM8/5/13
to expre...@googlegroups.com
So the more I thought about it, the more I realized that I don't like the authorization inside the routing middleware. It is a cross-cutting concern and should be elevated above. 

So I took what I had done, and rolled it into cansecurity, so it now supports authentication, sessions (native and express), stateless sessions (across nodejs instances), middleware authorization, AND declarative authorization. All supported in cansecurity v0.5.0 and up.

And I took the opportunity to completely clean up my tests - moved them to mocha+supertest, sooo much cleaner. 

I'll send out a separate announcement. 
Reply all
Reply to author
Forward
0 new messages