Pesquisa de site

javascript - Como misturar autenticação JWT com ACLs


Eu consegui implementar o passport usando uma estratégia JWT, e funciona bem. Minhas rotas protegidas por JWT ficam assim...

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

Agora eu preciso restringir o acesso de algumas coisas apenas para usuários logados que pertençam a algum papel. Eu gostaria de poder expressar isso assim:

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

Onde MAGIC=exigir usuários logados, mas apenas aqueles com a função x ou y

node_acl parece uma boa solução, e eu entendo até certo ponto, mas então encontro isto na documentação...

Podemos proteger um recurso assim:

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

O middleware protegerá o recurso nomeado por req.url, selecionará o usuário de req.session.userId e verificará a permissão para req.method, então o acima seria equivalente a algo como isto:

Como faço para misturar isso com minha estratégia JWT? Minha única ideia é abrir mão do middleware do node_acl e, em vez disso, adicionar código de verificação de ACL à minha estratégia JWT. Mas é aí que encontro problemas. Minha função JWT se parece com isto:

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
        }
    });
}));

De acordo com node_acl, eu posso perguntar algo assim...

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

Então eu posso (devo?) alterar minha JwtStrategy para dizer algo como...

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

se sim, como essa função vai saber o nome do recurso 'blogs' e as permissões ['edit' etc]? Estes são conhecidos no momento em que a rota é definida, mas eu acho que preciso deles na função de estratégia. Estou fazendo isso de forma completamente errada? Alguém pode me mostrar a forma certa?

Resposta #1

app.get('/thingThatRequiresLogin/:id', 
  [
     passport.authenticate('jwt', { session: false }), 
     acl.middleware( 1, getUserId )
  ], 
  thingThatRequiresLogin.findById);

pegando uma dica deste gist: https://gist.github.com/danwit/e0a7c5ad57c9ce5659d2 e da documentação do node_acl no npm: https://www.npmjs.com/package/acl#middleware acl.middleware aceita três argumentos opcionais: acl.middleware(numPathComponents, userId, permissions)

numPathComponents: 1 //para selecionar o caminho thingThatRequiresLogin

userId: getUserId //getUserId é uma função que retorna userId

Espero que isso ajude