web-dev-qa-db-ja.com

Passport.jsがユーザーのシリアル化に失敗する

私はGoogle、Facebook、Twitterのログインにのみpassport.jsを使用しています。

Node.jsv0.8.19とexpress.js3.1.0、およびpassportjsバージョン0.1.16。 (passport-facebook-0.1.5、Twitter-0.1.4 passport-goolge-oauth-0.1.5)

Passport.jsを実行しているアプリが1時間ほど経過すると、ユーザーのreq.userセッションへのシリアル化が停止するため、しばらくの間はすべて正常に機能します。

FacebookとGoogleは、それぞれのAPIから意味のある完全なデータを受信して​​います

passport.use(new FacebookStrategy({
    clientID: FACEBOOK_APP_ID,
    clientSecret: FACEBOOK_APP_SECRET,
    callbackURL: "http://localhost:3000/auth/facebook/callback"
  },
  function(accessToken, refreshToken, profile, done) {
      var temp = {} 
      temp.name = profile.displayName
      temp.id = profile.id
      console.log(temp)
      return done(null, temp);
}));

ここのconsole.logは、ユーザーIDと名前を正常に出力しますが、呼び出した後

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

passport.deserializeUser(function(obj, done) {
  done(null, obj);
});

シリアル化と逆シリアル化はパスポートから取得されます-facebook

ユーザーはreq.userに接続されません。

Twitterは、コールバックURLに戻った後、エラーを出します。

Error: failed to find request token in session
[03/11 23:28:24 GMT]     at Strategy.OAuthStrategy.authenticate            

注:これらの障害は一定期間後にのみ発生し、しばらくの間は正常に機能します。そのため、セッションをクックではなくメモリに保存するなど、メモリの問題である可能性があると思います。

これは私のエクスプレスアプリの構成です

app.configure(function(){
  app.set('port', process.env.PORT || 8080);
  app.set('views', __dirname + '/views');
  app.set('view engine', 'jade');
  app.use(express.favicon());
  app.use(express.logger('dev'));
  app.use(express.cookieParser());
  app.use(express.bodyParser());
  app.use(express.methodOverride());
  app.use(express.cookieSession({ secret: 'tobo!', cookie: { maxAge: new Date(Date.now() +     3600000), }}));
  app.use(passport.initialize());
  app.use(passport.session());
  app.use(app.router);
  app.use(express.static(__dirname + '/public'));
});

メーリングリストなどを見てきましたが、この問題に一致するものが見つかりませんでした。ローカルホストとnodejitsuサーバーを確認しました。すべてがしばらくの間機能し、その後失敗します。

10
Eoin Murray

まず、シリアル化と逆シリアル化の意味を理解する必要があります。

1)serializeUserは、最初の質問のように、done(null, user)を返すときに、ユーザーオブジェクトを取得し、セッションに必要な情報を格納します。

2)deserializeUserは、セッションに保存されている情報(すべてのリクエストでcookieSessionによって送信される)を取得し、セッションがユーザーに対してまだ有効であるかどうかを確認し、if(!err) done(null,user)がtrueの場合、ユーザーをセッション。else done(err,null)はセッションからセッションを削除し、セッションがタイムアウトしたかどうかを確認した後、app.get('/auth/:provider/callback')がユーザーに送信する場所にリダイレクトします。これにより、2番目の質問の内容が明確になります。

26
Marcel

なぜ問題が発生したのかはまだわかりませんが、次のようにして解決しました。

変化

  app.use(express.cookieSession({ secret: 'tobo!', cookie: { maxAge: new Date(Date.now() +     3600000), }}));

app.use(express.cookieSession({ secret: 'tobo!', maxAge: 360*5 }));

DeserializeUserは渡されたCookieを返すだけなので、ユーザーオブジェクト全体のシリアル化は機能するはずだと思います。しかし、ユーザーオブジェクト全体をシリアル化しないことで、機能しています。

passport.serializeUser(function(user, done) {
    console.log('serializeUser: ' + user._id)
    done(null, user._id);
});

passport.deserializeUser(function(id, done) {
    db.users.findById(id, function(err, user){
        console.log(user)
        if(!err) done(null, user);
        else done(err, null)  
    })
});

これを行ってから、ゼロの問題が発生しました。

6
Eoin Murray