passport-local mit node-jwt-simple

87

Wie kann ich passport-local kombinieren, um bei erfolgreicher Authentifizierung ein JWT-Token zurückzugeben?

Ich möchte node-jwt-simple verwenden und mir passport.js ansehen. Ich bin mir nicht sicher, wie ich vorgehen soll .

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

Ist es möglich, das Token beim Aufruf von done () zurückzugeben? So etwas wie das ... (nur Pseudocode)

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

Wenn nicht, wie kann ich den Token zurückgeben?

cgiacomi
quelle

Antworten:

123

Ich habe es herausgefunden!

Zunächst müssen Sie die richtige Strategie umsetzen. In meinem Fall LocalStrategy, und Sie müssen Ihre Validierungslogik angeben. Verwenden wir zum Beispiel die in passport-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);
    });
  }
));

Der von Ihnen bereitgestellte Rückruf zur Überprüfung sorgt function(username, password, done)dafür, dass Ihr Benutzer gefunden und überprüft wird, ob das Kennwort übereinstimmt (über den Rahmen der Frage und meiner Antwort hinaus).

passport.js erwartet, dass mehrere Teile funktionieren. Zum einen geben Sie den Benutzer in die Strategie zurück. Ich habe versucht, diesen Teil des Codes zu ändern, und das war falsch. Der Rückruf erwartet, falsewenn die Validierung fehlschlägt, und einen object(validierten Benutzer), wenn Sie erfolgreich sind.

Nun ... wie kann man JWT integrieren?

In Ihrer Login-Route müssen Sie eine erfolgreiche oder eine nicht erfolgreiche Authentifizierung durchführen. Und hier müssen Sie die Erstellung des JWT-Tokens hinzufügen. Wie so:

(Denken Sie daran, die Sitzung zu deaktivieren, da Sie sonst die Funktionen zum Serialisieren und Deserialisieren implementieren müssen. Diese benötigen Sie nicht, wenn Sie die Sitzung nicht beibehalten, was Sie nicht tun, wenn Sie eine tokenbasierte Authentifizierung verwenden.)

Aus passpasslokalen Beispielen: (mit hinzugefügtem JWT-Token)

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

Und das ist alles! Wenn Sie jetzt anrufen / sich anmelden und Benutzername und Passwort POSTEN (was immer über SSL erfolgen sollte), versucht das erste Code-Snippet oben, einen Benutzer anhand des von Ihnen angegebenen Benutzernamens zu finden, und überprüft dann, ob das Passwort übereinstimmt (natürlich müssen Sie dies tun) ändern Sie das, um Ihren Bedürfnissen zu entsprechen).

Danach wird Ihre Login-Route aufgerufen und Sie können sich darum kümmern, einen Fehler oder ein gültiges Token zurückzugeben.

Hoffe das wird jemandem helfen. Und wenn ich Fehler gemacht oder etwas vergessen habe, lass es mich wissen.

cgiacomi
quelle
3
Passports BasicStrategy oder DigestStrategy sind zwei weitere Optionen. Es scheint jedoch keinen großen Unterschied zwischen Basis- und lokalen Strategien zu geben, da keine der beiden Sitzungen zum Funktionieren erforderlich ist - nur, dass Local nach Umleitungs-URLs fragt (was die API-Qualität etwas verringert).
Funseiki
1
Hey @cgiacomi, könnten Sie ein Beispiel für eine Route geben, die den Token überprüft?
Matt Kim
3
Hey @ matt-kim eigentlich speichere ich das Token nicht, es ist vorübergehend. Ich weiß nicht, ob es der beste Weg ist oder nicht, aber ich mache Folgendes: Der Benutzer authentifiziert sich, generiert das Token und gibt es an den Client zurück. Das Token wird in localStorage gespeichert, wenn es sich bei dem Client um eine Website handelt, oder Sie können es in einer iPhone / Android-App speichern. Wenn ein Client eine Anforderung für eine Ressource stellen muss, sendet er das gespeicherte Token an das Backend. Der Reisepass übernimmt den Token. Hier ist eine Zusammenfassung der Bearer-Strategie für den Umgang mit dem Token gist.github.com/cgiacomi/cd1efa187b8cccbe2a61 Hoffe, dies hilft! :)
cgiacomi
1
Hey @cgiacomi! Vielleicht ist es offensichtlich, aber können Sie beschreiben, wie Sie die Sitzungen deaktivieren, wenn Sie den benutzerdefinierten Rückruf verwenden?
MrMuh
2
@MrMuh checkout den Link gist.github.com/cgiacomi/cd1efa187b8cccbe2a61 in meinem Kommentar Ich zeige, wie man Sitzungen deaktiviert: passport.authenticate ('Inhaber', {Sitzung: falsch})
cgiacomi
18

Dies ist eine großartige Lösung. Ich möchte nur Folgendes hinzufügen:

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

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

Ich verwende gerne "express-jwt" , um das Token zu validieren.

Übrigens: In diesem Artikel erfahren Sie, wie Sie mit dem Token auf der Clientseite mithilfe von Angular umgehen, um es bei jeder Anforderung zurückzusenden

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

ZeroCR
quelle
2
Ich habe bisher nur express-jwtdie Authentifizierung durchgeführt, aber ich habe die Dokumentation anderer Pakete durchgelesen, z. B. passport-jwtich denke, ich werde mich daran halten express-jwt. Viel einfacher, viel schöner IMO
Bobbyz
Nur ein FYI Express-JWT bietet keine Unterstützung für Aktualisierungstoken.
user3344977