passeport-local avec node-jwt-simple

87

Comment puis-je combiner passeport local pour renvoyer un jeton JWT en cas d'authentification réussie?

Je veux utiliser node-jwt-simple et en regardant passeport.js je ne sais pas trop comment s'y prendre.

var passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function(err, user) {
      if (err) { return done(err); }
      if (!user) {
        return done(null, false, { message: 'Incorrect username.' });
      }
      if (!user.validPassword(password)) {
        return done(null, false, { message: 'Incorrect password.' });
      }
      return done(null, user);
    });
  }
));

Est-il possible de retourner le jeton lors de l'appel de done ()? Quelque chose comme ça ... (juste du pseudo code)

if(User.validCredentials(username, password)) {
  var token = jwt.encode({username: username}, tokenSecret);
  done(null, {token : token}); //is this possible?
}

Sinon, comment puis-je retourner le jeton?

cgiacomi
la source

Réponses:

123

Je l'ai compris!

Tout d'abord, vous devez mettre en œuvre la bonne stratégie. Dans mon cas, LocalStrategy, et vous devez fournir votre logique de validation. Par exemple, utilisons celui de passeport local.

var passport = require('passport')
  , LocalStrategy = require('passport-local').Strategy;

passport.use(new LocalStrategy(
  function(username, password, done) {
    User.findOne({ username: username }, function(err, user) {
      if (err) { return done(err); }
      if (!user) {
        return done(null, false, { message: 'Incorrect username.' });
      }
      if (!user.validPassword(password)) {
        return done(null, false, { message: 'Incorrect password.' });
      }
      return done(null, user);
    });
  }
));

le rappel de vérification que vous fournissez function(username, password, done)se chargera de trouver votre utilisateur et de vérifier si le mot de passe correspond (au-delà de la portée de la question et de ma réponse)

passeport.js attend plusieurs éléments pour que cela fonctionne, l'un est que vous renvoyez l'utilisateur dans la stratégie. J'essayais de changer cette partie du code, et c'était faux. Le rappel attend falsesi la validation échoue et un object(l'utilisateur validé) si vous réussissez.

Maintenant .... comment intégrer JWT?

Dans votre itinéraire de connexion, vous devrez gérer une authentification réussie ou infructueuse. Et c'est ici que vous devez ajouter la création de jeton JWT. Ainsi:

(n'oubliez pas de désactiver la session, sinon vous devrez implémenter les fonctions de sérialisation et de désérialisation. Et vous n'en avez pas besoin si vous ne persistez pas la session, ce que vous n'êtes pas si vous utilisez une authentification basée sur un jeton)

À partir d'exemples locaux de passeport: (avec le jeton JWT ajouté)

// POST /login
//   This is an alternative implementation that uses a custom callback to
//   achieve the same functionality.
app.post('/login', function(req, res, next) {
  passport.authenticate('local', function(err, user, info) {
    if (err) { return next(err) }
    if (!user) {
      return res.json(401, { error: 'message' });
    }

    //user has authenticated correctly thus we create a JWT token 
    var token = jwt.encode({ username: 'somedata'}, tokenSecret);
    res.json({ token : token });

  })(req, res, next);
});

Et c'est tout! Maintenant, lorsque vous appelez / connectez-vous et POST le nom d'utilisateur et le mot de passe (qui doivent toujours être sur SSL), le premier extrait de code ci-dessus essaiera de trouver un utilisateur en fonction du nom d'utilisateur que vous avez fourni, puis vérifiera que le mot de passe correspond (bien sûr, vous devrez changez-le en fonction de vos besoins).

Après cela, votre itinéraire de connexion sera appelé et vous pourrez y retourner une erreur ou un jeton valide.

J'espère que cela aidera quelqu'un. Et si j'ai commis des erreurs ou oublié quelque chose, faites-le moi savoir.

cgiacomi
la source
3
Passeport BasicStrategy ou DigestStrategy sont deux autres options. Il ne semble pas y avoir de différence énorme entre les stratégies de base et locales, car aucune des deux sessions n'a besoin de fonctionner - juste que Local demande des URL de redirection (ce qui le rend légèrement moins convivial pour l'API).
funseiki
1
Hey @cgiacomi pourrais-tu donner un exemple d'itinéraire qui vérifie le jeton?
Matt Kim
3
Hey @ matt-kim en fait, je ne sauvegarde pas le jeton, c'est transitoire. Je ne sais pas si c'est le meilleur moyen ou non, mais c'est ce que je fais: l'utilisateur s'authentifie, je génère le jeton et le retourne au client. Le jeton est stocké dans localStorage si le client est un site Web, ou vous pouvez le stocker dans une application iPhone / Android. Lorsqu'un client doit faire une demande pour une ressource, il envoie le jeton enregistré au backend. Passport gérera le jeton. Voici l'essentiel de la stratégie Bearer pour gérer le jeton gist.github.com/cgiacomi/cd1efa187b8cccbe2a61 J'espère que cela vous aidera! :)
cgiacomi
1
Salut @cgiacomi! c'est peut-être évident, mais pourriez-vous décrire comment vous désactivez les sessions lorsque vous utilisez le rappel personnalisé?
MrMuh
2
@MrMuh consultez le lien gist.github.com/cgiacomi/cd1efa187b8cccbe2a61 dans mon commentaire je montre comment désactiver les sessions: passeport.authenticate ('porteur', {session: false})
cgiacomi
18

C'est une excellente solution, je veux juste ajouter ceci:

var expressJwt = require('express-jwt');

app.use('/api', expressJwt({secret: secret}));

J'aime utiliser "express-jwt" pour valider le jeton.

btw: cet article est idéal pour apprendre à gérer le jeton côté client, en utilisant Angular, afin de le renvoyer à chaque demande

https://auth0.com/blog/2014/01/07/angularjs-authentication-with-cookies-vs-token/

ZeroCR
la source
2
Je ne faisais que l' express-jwtauthentification, mais en lisant la documentation d'autres paquets tels que passport-jwt, je pense que je vais m'en tenir express-jwt. Beaucoup plus simple, beaucoup plus agréable IMO
bobbyz
Juste un FYI express-jwt ne prend pas en charge les jetons d'actualisation.
user3344977