Wyszukiwanie w witrynie

javascript - Jak łączyć uwierzytelnianie jwt z ACL


Udało mi się zaimplementować Passport używając strategii JWT i działa to dobrze. Moje trasy chronione przez JWT wyglądają tak...

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

Teraz muszę ograniczyć dostęp do niektórych rzeczy tylko dla zalogowanych użytkowników należących do określonej roli. Chciałbym móc wyrazić to w taki sposób:

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

Gdzie MAGIC=wymaga zalogowanych użytkowników, ale tylko tych z rolą x lub y

node_acl wydaje się być dobrym rozwiązaniem i rozumiem to do pewnego stopnia, ale potem znajduję to w dokumentacji...

Możemy chronić zasób w ten sposób:

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

Middleware będzie chronić zasób o nazwie podanej w req.url, wybierze użytkownika z req.session.userId i sprawdzi uprawnienia dla req.method, więc powyższe byłoby równoważne z czymś takim:

Jak mogę połączyć to z moją strategią JWT? Moim jedynym pomysłem jest zrezygnowanie z middleware node_acl i zamiast tego dodanie kodu do sprawdzania ACL do mojej strategii JWT. Ale tutaj napotykam problemy. Moja funkcja JWT wygląda tak:

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

Zgodnie z node_acl, mogę zapytać o coś takiego...

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

Czy więc mogę (czy powinienem?) zmienić moją JwtStrategy, aby powiedzieć coś w stylu...

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

Jeśli tak, jak ta funkcja będzie wiedziała o nazwie zasobu 'blogs' i uprawnieniach ['edit' itd.]? Są one znane w momencie definiowania trasy, ale myślę, że potrzebuję ich w funkcji strategii. Czy podchodzę do tego całkowicie źle? Czy ktoś mógłby pokazać mi właściwy sposób?

Odpowiedź #1

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

czerpiąc wskazówkę z tego gista: https://gist.github.com/danwit/e0a7c5ad57c9ce5659d2 oraz dokumentacji node_acl na npm: https://www.npmjs.com/package/acl#middleware acl.middleware przyjmuje trzy opcjonalne argumenty: acl.middleware(numPathComponents, userId, permissions)

numPathComponents: 1/aby wybrać ścieżkę thingThatRequiresLogin

userId: getUserId //getUserId to funkcja, która zwraca userId

Mam nadzieję, że to pomoże