Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mix jwt authentication with ACLs

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?

like image 702
user1272965 Avatar asked Mar 05 '16 19:03

user1272965


People also ask

How can you implement authentication with a JWT?

To authenticate a user, a client application must send a JSON Web Token (JWT) in the authorization header of the HTTP request to your backend API. API Gateway validates the token on behalf of your API, so you don't have to add any code in your API to process the authentication.

Can I use JWT with Passport?

A Passport strategy for authenticating with a JSON Web Token. This module lets you authenticate endpoints using a JSON web token. It is intended to be used to secure RESTful endpoints without sessions.

Which is better Passport or JWT?

JSON Web Token and Passport can be primarily classified as "User Management and Authentication" tools. JSON Web Token and Passport are both open source tools. It seems that Passport with 15.9K GitHub stars and 936 forks on GitHub has more adoption than JSON Web Token with 2.59K GitHub stars and 259 GitHub forks.

What is difference between access token and JWT?

The OAuth access token is different from the JWT in the sense that it's an opaque token. The access token's purpose is so that the client application can query Google to ask for more information about the signed in user. email: The end user's email ID. email_verified: Whether or not the user has verified their email.


1 Answers

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

like image 82
jsphadetula Avatar answered Sep 28 '22 05:09

jsphadetula