web-dev-qa-db-fra.com

Authentification de l'API de noeud avec passport-jwt

J'essaie de configurer l'authentification JWT à l'aide de passport-jwt. Je pense avoir pris les bonnes mesures, mais un test GET n'aboutira pas et je ne sais pas comment le déboguer.

Voici ce que j'ai fait:

  1. setup passport-jwt tout droit sorti de la doc autant que possible

    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. Ajout d'un résultat de jeton sur mon point de connexion utilisateur/connexion

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

Les choses allaient bien jusque là. Je peux connecter un utilisateur (en utilisant passeport local auth) et la réponse a été celle que j'espérais ...

{ "utilisateur": { "_id": "56c8b5bd80d16ef41ec705dd", "email": "[email protected]", "mot de passe": "$ 2a $ 10 $ zd ... etc.", "__v": 0, }, "jwtToken": "JWT eyJ0eXAiOiJ .... etc." }

J'ai créé un itinéraire de test non protégé comme celui-ci ...

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

Et dans mon contrôleur, un point final simple ...

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

Et GET-ing qui fonctionne bien aussi.

  1. Mais alors j'essaie de protéger cette route comme ceci: 

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

Après cela, rien que de la tristesse. J'envoie une demande comme celle-ci:

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

Et toujours, toujours obtenir un 401:

Non autorisé

Les journaux de la console dans le contrôleur ne semblent pas s'exécuter, pas plus que la journalisation dans la méthode de stratégie passport.use. J'ai modifié et modifié, mais je suis un peu perdu. Le passeport-jwt doc fournit juste l'exemple, et pratiquement aucune autre aide.

S'il vous plaît, des idées sur une erreur que je fais ci-dessus, ou au moins sur la façon de procéder au débogage ??

14
user1272965

Pour toute pauvre âme qui me suit ici: le passeport-jwt doc implique que l'en-tête d'authentification devrait ressembler à ceci ...

Autorisation: JWT JSON_WEB_TOKEN_STRING .....

Cela s'est avéré être trompeur (pour moi, en tout cas).

Heureusement, grâce à cet article j'ai pu apprendre comment le jeton est construit. (Le préfixe du jeton jusqu'au premier "." Correspond au codage base64 du schéma. Ce "JWT" ​​à l'avant était un bruit empêchant la validation de fonctionner.

Le correctif consistait donc à modifier le jeton renvoyé par le contrôleur utilisateur à partir de:

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

Pour le plus simple:

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

Phew. Est-ce moi, ou est-ce vraiment une déception de voir à quel point ces choses sont expliquées dans tant de documentation de paquet de nœuds?

26
user1272965

Je peux être en retard mais j'ai eu un problème similaire et j'ai une autre solution. Vous pouvez utiliser cette options.jwtFromRequest = ExtractJwt.fromAuthHeaderWithScheme('JWT') pour extraire le jeton JWT de l'en-tête d'authentification au format suivant: 

Autorisation: JWT JSON_WEB_TOKEN_STRING .....

Voici la documentation que j'ai utilisée: https://github.com/themikenicholson/passport-jwt

Extraire le JWT de la requête

Le JWT peut être inclus dans une demande de plusieurs manières. Dans Afin de rester aussi flexible que possible, le JWT est analysé à partir du fichier demande par un rappel fourni par l'utilisateur transmis en tant que jwtFromRequest paramètre. Ce rappel, appelé désormais extracteur, accepte un objet de requête en tant qu'argument et retourne le fichier JWT codé chaîne ou null. Extracteurs inclus

Un certain nombre de fonctions d’usine d’extracteur sont fournies dans passport-jwt.ExtractJwt. Ces fonctions d'usine renvoient un nouveau extracteur configuré avec les paramètres donnés.

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