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
