web-dev-qa-db-ja.com

PassportJS deserializeUserが呼び出されたことがない

Mongodbに保存されているユーザーを認証するためのPassportセットアップがあります。正常に動作しているようです。認証は適切に成功/失敗し、セッション変数が設定されます。ただし、Passportでセッションを確認することはできません。私がdeserializeUserコールバックに追加したconsole.logステートメントが日の目を見ることがないので、何かがかなり間違っているようです。私の問題は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);
37
Alex Westholm

この問題が発生している他の人のために、これを見てください:

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

あなたが持っている場合 cookie.secureをtrueに設定し、SSL(つまり、httpsプロトコル)を使用していない場合、セッションIDを含むCookieはブラウザに返されず、すべてが警告なしに失敗します。このフラグを削除すると問題が解決しました。これを実現するのに何時間もかかりました!

35
Dave Kerr

パスポートで認証するときにauthenticateコールバックを使用している場合は、ユーザーを手動でログインする必要があります。それはあなたのために呼ばれることはありません。

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

ミドルウェアをuse()してpassport.session()しましたか?この例のように:

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

これがセッションを復元してdeserializeUserを呼び出すものなので、欠落している可能性があります。

12
Jared Hanson

さて、これは私が解決するのにほぼ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;しかし、それはその要点です。

3
Sharukh Mastan

私は一日中同じ問題と戦った。承認を行うためにカスタムコールバックを設定しました(- 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);

 }
1
user3522492

私の場合、それは私がこのコードを持っていたためです:

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

どうやらこの場合、req.login()は呼び出されません(deserializeを呼び出します)。私はそれをこれに変更し、うまくいきました:

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

私の場合は、

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

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

そしてそれは働いた。

0
Prakash Ujjwal

今日、私は同じ問題に直面しましたが、私の場合、原因はクライアント側が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が正しく呼び出されるようになりました。

0
dhilt