Подтвердить что ты не робот

PassportJS deserializeUser никогда не вызывал

У меня есть настройка Passport для аутентификации пользователей, хранящихся в mongodb. Кажется, что он работает нормально: аутентификация успешно завершается/выполняется надлежащим образом, и параметры сеанса устанавливаются. Однако получение паспорта для проверки сеанса не выполняется. Что-то кажется неправильным в том, что инструкции console.log, которые я добавил в обратный вызов deserializeUser, никогда не видят свет дня. Я предполагаю, что моя проблема связана с deserializeUser, никогда не вызываемой. Любой, кто может диагностировать мои ошибки?

// Passport configuration
passport.serializeUser(function(user, cb){ cb(null, user.id) });
passport.deserializeUser(function(uid, cb){
  console.log("Trying to deserialize user: "+uid);
  User.findById(uid, function(err, user){
    cb(err, user);
  });
});
// auth strategy function
passport.use(new LocalStrategy({usernameField: 'email'},
  function(email, pass, done){
    User.findOne({email: email}, function (err, user) {
      if (err)
        return done(err);
      if (!user)
        return done(null, false, {message: "Couldn't find user"});
      var crypted = bcrypt.hashSync(pass, user.salt);
      if(user.hashpass != crypted)
        return done(null, false, {message: "Bad password"});
      return done(null, user);
    });
  }
));

passport.CreateSession =  function (req, res, next) {
  passport.authenticate('local', function(err, user, info){
    if(err || !user)
      return res.json({status: "Failure: "+err});
    req.logIn(user, function (err){
      if(err)
        return res.json({status: "Failure: "+err});
      return res.json({status: "Authenticated"});
    });
  })(req, res, next);
};

со следующим в app.js:

app.post('/session', passport.CreateSession); // restify better
app.del('/session', passport.DestroySession);
app.get('/images', passport.CheckSession, routes.images);
4b9b3361

Ответ 1

Для всех, кто имеет эту проблему, взгляните на это:

app.use(session({ 
    secret: 'something', 
    cookie: { 
        secure: true
    }}));

Если у вас cookie.secure установлено значение true, и вы НЕ используете SSL (т.е. протокол https), cookie с идентификатором сеанса не возвращается в браузер и все терпит неудачу. Удаление этого флага разрешило проблему для меня - потребовалось несколько часов, чтобы понять это!

Ответ 2

Если вы используете обратный вызов authenticate при аутентификации с паспортом, вам необходимо вручную зарегистрировать пользователя. Это не будет вызвано для вас.

passport.authenticate('local', function (err, user) {
    req.logIn(user, function (err) { // <-- Log user in
       return res.redirect('/'); 
    });
})(req, res);

Ответ 3

Вы use() промежуточное программное обеспечение use() passport.session()? Как в этом примере:

https://github.com/jaredhanson/passport-local/blob/v1.0.0/examples/login/app.js#L91

То, что восстанавливает сессию и вызывает deserializeUser, так что может показаться, что этого не хватает.

Ответ 4

Хорошо, это заняло у меня почти 3 дня, чтобы решить, что кажется простым решением, по крайней мере, в моем случае. Мне пришлось разместить app.use(require('cookie-parser')); и app.use(require('express-session')({ secret: 'keyboard cat', resave: false, saveUninitialized: false })); ДО вызова:

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

Примечание. Эти фрагменты не являются моим настоящим кодом, я взял его из: https://github.com/passport/express-4.x-local-example > server.js file; но это суть этого.

Ответ 5

Я боролся с одной и той же проблемой весь день. У меня был настроен обратный вызов для авторизации (как внизу http://passportjs.org/guide/authenticate/). Похоже, что Passport предварительно обрабатывает все объекты запроса еще до того, как они попадут в другое промежуточное программное обеспечение (на основе некоторых операторов журналирования, которые я написал). Как часть этой предварительной обработки, он помещает десериализованную пользовательскую информацию в объект request.user. К сожалению, поведение по умолчанию passport.authenticate('local', callback), по-видимому, игнорирует любые сеансы или данные cookie и вместо этого предполагает, что имя пользователя и PW отправляются в объекте запроса. Чтобы исправить это, я сначала проверил объект request.user, и, если он существовал, это означало, что Passport выполнил предварительную обработку, а затем я мог напрямую вызвать login. Вот моя функция авторизации, которую я использую вместо passport.authenticate('local'):

function doAuth(request, response, next)
{ 

if (request.user) {
    request.logIn(request.user, function (err) {
        if (err) {
            console.log(err);
            response.status(500).json({message:
                    "Login failed. Auth worked. Nonsense"});
            return;
        }
        console.log("doAuth: Everything worked.");
        next();
    });
    return;
}

passport.authenticate('local', function(err, user, info) {
    if (err) {
        response.status(500).json({message: "Boo Passport!"});
        return; //go no further
        //until I figure out what errors can get thrown
    }
    if (user === false) {
        console.log("Authentication failed. Here is my error:");
        console.log(err);
        console.log("Here is my info:");
        console.log(info);
        response.status(500).json({message: "Authentication failed."});
        return;
    }
    request.logIn(user, function(err) {
        if (err) {
        console.log("Login failed. This is the error message:");
        console.log(err);
        response.status(500).json({message:"Login failed."});
            return;
        }
        console.log("doAuth: Everything worked. I don't believe it.");

        next();
    });
})(request, response, next);

 }

Ответ 6

Сегодня я столкнулся с той же проблемой, и в моем случае причиной было то, как клиентская сторона вызывает вызовы API. И следующий подход помог мне преодолеть проблему:

const doFetch(url, method = 'GET', body) {
  const headers = new Headers();
  headers.append('Content-Type', 'application/json');
  headers.append('Accept', 'application/json');
  headers.append('Cache', 'no-cache');
  const params = { 
    method, headers, 
    credentials: 'include' // The cookie must be sent!
  }
  if(body) {
    params.body = body;
  }
  return fetch(url, params);
}

После этого deserializeUser стал правильно называться.

Ответ 7

В моем случае это было потому, что у меня был этот код:

app.get("/auth/google/callback", 
    passport.authenticate("google", { 
        failureRedirect: "/admin/login/?error",
    }),
    (req, res) => {
        return res.redirect("/admin/");
    },
);

Очевидно, что в этом случае req.login() не будет вызываться (что вызывает десериализацию). Я изменил это на это, и это сработало:

app.get("/auth/google/callback", 
    passport.authenticate("google", { 
        successRedirect: "/admin/", 
        failureRedirect: "/admin/login/?error",
    })
);

Ответ 8

в моем случае я поместил

app.use(cookieSession({
  maxAge : 60*60*1000,
  keys : [key.cookieSession.key1]
}));

выше

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

и это сработало.

Ответ 9

убедитесь, что строка кода app.use(express.static(path.join(__dirname, 'public'))); остается ниже app.use(require('express-session')

Ответ 10

passport.serializeUser(
    function(user, done){
        done(null, user.id);
});

passport.deserializeUser(
    function(id, done){
        User.findById(id, function(err, user){
            if(err){
                done(err);
            }
            done(null, user);
        });
});

**> try this one**