Обратный вызов проверки подлинности паспорта, не вызывающий промежуточное ПО паспорта

Я пытаюсь проверить, защищен ли запрос GET на определенный маршрут с помощью веб-токенов JSON с паспортом JwtStrategy; однако похоже, что функция промежуточного программного обеспечения passport.use в моем файле server.js не выполняется. Console.log, который у меня есть, никогда не отображается в моей оболочке/терминале. Мой маршрут входа работает, но не маршрут профиля. Я использую почтальона, и я ввел http://localhost:3000/profile для метода GET, а на вкладке Headers я выбрал авторизацию для ключа, а для значения я скопировал и вставил длинную строку веб-токена JSON, но он продолжает говорить неавторизованным. Это потому, что моя функцияpassport.use никогда не выполняется.

//Файл Server.js

var JwtStrategy = require("passport-jwt").Strategy;
var ExtractJwt = require("passport-jwt").ExtractJwt;

var User = require("../models/user");
var config = require('./secret');

app.use(passport.initialize());
app.use(passport.session());

let options = {};
//pass token back and forth
options.jwtFromRequest = ExtractJwt.fromAuthHeader();
options.secretOrKey = config;
passport.use(new JwtStrategy(options, (jwt_payload, done) => {
  *******************************************
  //this console log doesn't show up in shell which makes be believe its never getting here
  *******************************************
  console.log("JWT PAYLOAD", jwt_payload)
  User.getUserById(jwt_payload._id, (err, user) => {
    if(err){
      return done(err, false);
    }

    if(user){ //null for error
      return done(null, user);
    }else{
      return done(null, false);
    }
  });
}));

//Файл маршрутов, в котором вызывается обратный вызов паспорта.authenticate

var passport = require('passport');
var jwt = require('jsonwebtoken');
var secret = require('../config/secret')

var User = require('../models/user');

router.post('/login', (req, res) => {
    var username = req.body.username;
    var password = req.body.password;
    console.log("SECRET2", secret);
    console.log("SECRET", secret.secret);
    User.getUserByUsername(username, (err, user) => {
        if(err){
            throw err;
        }
        if(!user){
            return res.json({ success: false, msg: "User not found"});
        }

        User.comparePassword(password, user.password, (err, isMatch) => {
            if(err){
                throw err;
            }
            if(isMatch){
                var token = jwt.sign(user, secret.secret, {
                    expiresIn: 604800 //1 week in seconds, token expires and requires to log back in
                });

                console.log('TOKEN IN LOGIN ROUTE', token)

                res.json({
                    //tokens are then stored in local storage or cookie
                    success: true,
                    token: 'JWT ' + token,
                    user: {
                        id: user._id,
                        name: user.name,
                        username: user.username,
                        email: user.email
                    }
                });
            }else{
                return res.json({ success: false, msg: "Incorrect password"});
            }
        });
    });
});

router.get('/profile', passport.authenticate('jwt', {session:false}), (req, res) => {
    res.json({user: req.user});
});

//Модель пользователя

var mongoose = require('mongoose');
var bcrypt = require('bcryptjs');

var Schema = mongoose.Schema;

var UserSchema = new Schema({
  name: {
    type: String,
    trim: true,
    required: "First Name is Required"
  },
  email: {
    type: String,
    required: true
  },
  username: {
    type: String,
    required: true
  },
  password: {
    type: String,
    required: true
  }
});

var User = mongoose.model("User", UserSchema);

module.exports = User;

//Alternate syntax for exporting Schema
// var User = module.exports = mongoose.model("User", UserSchema);

module.exports.getUserById = function(id, callback){
    User.findById(id, callback);
}

module.exports.getUserByUsername = function(username, callback){
    var query = { username: username }
    User.findOne(query, callback);
}

//Custom User model function that will take in the newUser object and hash the password.
module.exports.addUser = function(newUser, callback){
    bcrypt.genSalt(10, (err, salt) => {
        bcrypt.hash(newUser.password, salt, (err, hash) => {
            if(err){
                throw err
            }

            newUser.password = hash;
            newUser.save(callback);
        });
    });
}

module.exports.comparePassword = function(password, hash, callback){
    bcrypt.compare(password, hash, (err, isMatch) => {
        if(err){
            throw err
        }
        callback(null, isMatch);
    });
}

Обновление: я попытался поставить пробел после «JWT» для значения «Авторизация» в почтальоне, но он все еще не работает, и журнал консоли не отображается. Это потому, что я каким-то образом не экспортирую или не связываю passport.use, который я определил в своем server.js, с моим маршрутом GET '/ profile' в моем файле маршрутов?

Обновление 2: добавлена ​​модель и маршрут входа


person henhen    schedule 07.05.2017    source источник
comment
Значение заголовка Authorization должно выглядеть так: JWT the-actual-token. Посмотрите здесь.   -  person robertklep    schedule 07.05.2017
comment
Вы имеете в виду, когда я тестирую на почтальоне путь GET к профилю? У меня установлен тип «Авторизация», а значение — весь токен jwt, который я вставил. Если мне не нужно это пространство JWT, то токен. Но я не уверен, что это проблема, поскольку метод Authenticate (passport.use), кажется, никогда не вызывается, потому что журнал консоли никогда не отображается.   -  person henhen    schedule 07.05.2017
comment
Да, вам нужно поставить префикс токена в значении с помощью JWT-space. Как сказано в документации, на которую я ссылался: github.com/ themikenicholson/ Я предполагаю, что стратегия никогда не вызывается, потому что заголовок Authorization недействителен.   -  person robertklep    schedule 07.05.2017
comment
Хорошо, я попытался добавить пробел, но он по-прежнему говорит о несанкционированном доступе, а журнал консоли по-прежнему не отображается. Нужен ли мне JWT плюс пробел, за которым следует токен?   -  person henhen    schedule 07.05.2017
comment
Нет. Допустим, ваш токен ABCDEF, тогда значение заголовка должно выглядеть так: JWT ABCDEF   -  person robertklep    schedule 07.05.2017
comment
Да, я пробовал оба способа, но результаты одинаковы. Похоже, мой паспорт. Использование никогда не выполняется в любом случае, поскольку журнал консоли, который у меня есть в моем исходном сообщении, никогда не отображается в моем терминале.   -  person henhen    schedule 07.05.2017
comment
А вы уверены, что токен, который вы передаете, действителен? Только когда он сможет найти действительный токен, будет вызван обратный вызов. Вот автономная версия, которая мне подходит: gist.github.com/robertklep/8183ef63e9520ce653934092cb8001f3   -  person robertklep    schedule 07.05.2017
comment
Да, я копирую токен, который возвращается из маршрута входа POST, отображаемого в Postman.   -  person henhen    schedule 07.05.2017
comment
Можете ли вы также добавить код из маршрута входа в свой вопрос?   -  person robertklep    schedule 07.05.2017
comment
хорошо, только что добавил   -  person henhen    schedule 08.05.2017
comment
Вы генерируете токен с помощью secret.secret, но в параметрах стратегии вы используете secret, что кажется неправильным. В качестве отступления: expiresIn должно быть в миллисекундах, а не в секундах (теперь срок действия истекает через 10 минут), и, строго говоря, JWT не должно быть частью токена.   -  person robertklep    schedule 08.05.2017
comment
У меня есть JWT, поэтому я могу вернуть его мне в Postman для тестирования маршрута профиля. Кроме того, я не думаю, что expiresIn имеет какое-либо значение. И секретный вопрос тоже не должен быть проблемой, но я попробую   -  person henhen    schedule 08.05.2017
comment
Я попытался изменить secret.secret на просто секрет, но получаю сообщение об ошибке, говорящее, что секрет должен быть строкой или буфером, поэтому я уверен, что проблема не в этом. Кроме того, даже если формат токена JWT неверен, не следует ли по-прежнему вызывать промежуточную часть паспорта. использовать и показывать консоль и возвращать ошибку? Проблема в паспорте. Почему-то никогда не звонили.   -  person henhen    schedule 08.05.2017
comment
@robertklep Да, вы были правы. Это была проблема с секретом. Спасибо   -  person henhen    schedule 08.05.2017
comment
Вчера вечером я понял, что ваш токен содержит полный пользовательский документ, включая поле пароля. Я не думаю, что вы хотите раскрывать так много через токен (токены не зашифрованы, любой может их прочитать).   -  person robertklep    schedule 08.05.2017
comment
Да. Спасибо за совет. Я убедился, что пароль не отправлен обратно. Однако знаете ли вы, безопасно ли отправлять обратно _id пользователя MongoDB и устанавливать его в атрибуте данных html или эквиваленте? Причиной этого может быть ссылка на пользователей, например, при переходе на страницу профиля пользователя.   -  person henhen    schedule 10.05.2017
comment
Довольно часто используется клиентская сторона этих идентификаторов (в URL-адресах или иным образом) для идентификации пользователей, так что это не имеет большого значения.   -  person robertklep    schedule 10.05.2017


Ответы (1)


Возможно, необходимо включить дополнительный код, чтобы увидеть вашу проблему, но похоже, что стратегия экспортируется неправильно. Когда вы создаете новую стратегию, вы можете указать «псевдоним», чтобы использовать ее в точке входа:

passport.use('local-login', new JwtStrategy(options, (jwt_payload, done) => {
    ....
}

router.get('/profile', passport.authenticate('local-login', {session:false}), (req, res) => {
    res.json({user: req.user});
});
person Manuel    schedule 07.05.2017