web-dev-qa-db-de.com

Authentifizierung der Knoten-API mit passport-jwt

Ich versuche, die JWT-Authentifizierung mit passport-jwt einzurichten. Ich glaube, ich habe die richtigen Schritte unternommen, aber ein Test-GET wird nicht erfolgreich sein, und ich weiß nicht, wie ich es debuggen kann.

Folgendes habe ich getan:

  1. setup passport-jwt direkt aus dem doc so viel wie möglich

    var jwtOptions = {
        secretOrKey: 'secret',
        issuer: "accounts.examplesoft.com",  // wasn't sure what this was, so i left as defaulted in the doc
        audience: "yoursite.net"   // wasn't sure what this was, so i left as defaulted in the doc
      };
    
    jwtOptions.jwtFromRequest = ExtractJwt.fromAuthHeader();
    
    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
        }
      });
    }));
    
  2. Token-Ergebnis zu meinem Benutzer/Login-Endpunkt hinzugefügt

    var jwt = require('jsonwebtoken');
    // ...
    
    exports.postLogin = function(req, res, next) {
      passport.authenticate('local', function(err, user, info) {
        if (err) throw err;
        if (!user) {
            return res.send({ msg: 'Login incorrect' });
        }
        req.logIn(user, function(err) {
            if (err) throw err;
            var secretOrKey = jwtOptions.secretOrKey;
            var token = jwt.sign(user, secretOrKey, {
                expiresIn: 631139040 // 20 years in seconds
            });
            res.send({ user: user, jwtToken: "JWT " + token });
        });
      })(req, res, next);
    };
    

Bis hier sah es gut aus. Ich kann einen Benutzer anmelden (mit Passport Local Auth) und die Antwort war eine, die ich gehofft hatte ...

{ "Nutzer": { "_id": "56c8b5bd80d16ef41ec705dd", "email": "[email protected]", "Kennwort": "$ 2a $ 10 $ zd ... etc.", "__v": 0, }, "jwtToken": "JWT eyJ0eXAiOiJ .... usw." }

Ich habe so eine ungeschützte Testroute erstellt ...

// in my routes file
app.get('/user/tokenTest', user.tokenTest);

Und in meinem Controller ein einfacher Endpunkt ...

exports.tokenTest = function(req, res) {
    console.log(req.headers);
    res.send("token test!!");
};

Und GET-ing funktioniert auch gut.

  1. Aber dann versuche ich diese Route so zu schützen: 

    app.get('/user/tokenTest', passport.authenticate('jwt', { session: false }),
        user.tokenTest);
    

Nachdem ich das getan habe, nichts als Traurigkeit. Ich sende eine Anfrage wie diese:

curl -k 'https://localhost:3443/user/tokenTest' -H 'Authorization: JWT eyJ0eXAiOiJ... etc.' 

Und immer, immer eine 401 bekommen:

Nicht autorisiert

Konsolenprotokolle im Controller scheinen nicht ausgeführt zu werden, ebenso wie die Protokollierung in der Strategiemethode passport.use. Ich habe und zwickte, aber ich bin ein wenig verloren. Das passport-jwt-Dokument liefert nur das Beispiel und praktisch keine andere Hilfe.

Bitte, irgendwelche Ideen über einen Fehler, den ich oben gemacht habe, oder zumindest, wie Sie mit dem Debugging umgehen können?

14
user1272965

Für jede arme Seele, die mir hier folgt: Der Pass-Jwt-Doc impliziert, dass der Auth-Header so aussehen sollte ...

Berechtigung: JWT JSON_WEB_TOKEN_STRING .....

Das stellte sich als irreführend heraus (für mich jedenfalls).

Zum Glück konnte ich dank diesem Artikel erfahren, wie der Token aufgebaut wird. (Das Präfix des Tokens bis zum ersten '.' Ist die Base64-Kodierung des Schemas. Dieses "JWT" ​​an der Vorderseite war ein Geräusch, das die Validierung daran hinderte, zu funktionieren.

Das Update bestand also darin, das vom Benutzer-Controller zurückgegebene Token zu ändern von:

    res.send({ user: user, jwtToken: "JWT " + token });

Zum einfacheren:

    res.send({ user: user, jwtToken: token });

Puh. Ist es mir, oder ist es wirklich ein Scheißkerl, wie unzureichend diese Dinge in so vielen Knotenpaket-Dokumenten erklärt werden?

26
user1272965

Ich komme zwar zu spät, hatte aber ein ähnliches Problem und habe eine andere Lösung. Mit diesem options.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('JWT') können Sie das JWT-Token aus dem Authentifizierungsheader im folgenden Format extrahieren: 

Berechtigung: JWT JSON_WEB_TOKEN_STRING .....

Hier ist die Dokumentation, die ich verwendet habe: https://github.com/themikenicholson/passport-jwt

Extrahieren der JWT aus der Anforderung

Es gibt verschiedene Möglichkeiten, wie die JWT in eine Anfrage aufgenommen werden kann. Im Um möglichst flexibel zu bleiben, wird die JWT aus der .__ analysiert. Anforderung durch einen vom Benutzer bereitgestellten Rückruf, der als jwtFromRequest .__ übergeben wird. Parameter. Dieser Rückruf, von nun an als Extraktor bezeichnet, akzeptiert ein Anforderungsobjekt als Argument und gibt die codierte JWT .__ zurück. Zeichenfolge oder Null. Enthaltene Extraktoren

Eine Reihe von Funktionen des Extraktors sind in .__ enthalten. passport-jwt.ExtractJwt. Diese werkseitigen Funktionen geben ein neues .__ zurück. Extraktor mit den angegebenen Parametern konfiguriert.

fromHeader(header_name) creates a new extractor that looks for the JWT in the given http header
fromBodyField(field_name) creates a new extractor that looks for the JWT in the given body field. You must have a body parser configured in order to use this method.
fromUrlQueryParameter(param_name) creates a new extractor that looks for the JWT in the given URL query parameter.
fromAuthHeaderWithScheme(auth_scheme) creates a new extractor that looks for the JWT in the authorization header, expecting the scheme to match auth_scheme.
fromAuthHeaderAsBearerToken() creates a new extractor that looks for the JWT in the authorization header with the scheme 'bearer'
fromExtractors([array of extractor functions]) creates a new extractor using an array of extractors provided. Each extractor is attempted in order until one returns a token.
0
Bruno Tavares