How to mix jwt authentication with ACLs
Asked Answered
C

1

6

I've been able to implement passport using a JWT strategy, and it works well. My jwt-protected routes look like this...

app.get('/thingThatRequiresLogin/:id', passport.authenticate('jwt', { session: false }), thingThatRequiresLogin.findById);

Now I need to restrict access for some things to only logged-in users belonging to some role. I wish I could express that like this:

app.get('/thingThatRequiresLogin/:id', MAGIC, thingThatRequiresLogin.findById);

Where MAGIC = require logged-in users, but only those with role x or y

node_acl seems like a good solution, and I understand it up to a point, but then I find this in the doc...

We can protect a resource like this:

app.put('/blogs/:id', acl.middleware(), function(req, res, next){…}

The middleware will protect the resource named by req.url, pick the user from req.session.userId and check the permission for req.method, so the above would be equivalent to something like this:

How do I mix this with my jwt strategy? My only idea is to forego the node_acl middleware and instead add acl-checking code to my jwt strategy. But that's where I run into trouble. My jwt function looks like this:

passport.use(new JwtStrategy(jwtOptions, function(jwt_payload, done) {
    User.findOne({id: jwt_payload.sub}, function(err, user) {
        if (err) {
            return done(err, false);
        }
        if (user) {
            done(null, user);
        } else {
            done(null, false);
            // or you could create a new account
        }
    });
}));

According to node_acl, I can ask something like this...

acl.isAllowed('jsmith', 'blogs', ['edit','view','delete'])

So can I (should I?) alter my JwtStrategy to say something like...

    if (user && acl.isAllowed(user.username, 'blogs', ['edit','view','delete']) {
        // ...

if so, how will this function know the resource name 'blogs' and the permissions ['edit' etc]? These are known at the point the route is defined, but I think I need them in the strategy function. Am I going about this all wrong? Can somebody show me the right way?

Carn answered 5/3, 2016 at 19:50 Comment(0)
B
7
app.get('/thingThatRequiresLogin/:id', 
  [
     passport.authenticate('jwt', { session: false }), 
     acl.middleware( 1, getUserId )
  ], 
  thingThatRequiresLogin.findById);

taking a clue from this gist: https://gist.github.com/danwit/e0a7c5ad57c9ce5659d2 and the node_acl doc on npm: https://www.npmjs.com/package/acl#middleware acl.middleware takes three optional arguments: acl.middleware(numPathComponents, userId, permissions)

numPathComponents: 1 //to select thingThatRequiresLogin path

userId: getUserId //getUserId is a function that returns userId

I hope this helps

Byword answered 28/8, 2016 at 0:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.