req.login()
をする前にreq.session.regenerate()
をすると良い。
セッション再生成
callback: function(req, res) {
passport.authenticate(strategy, {
callbackURL: ''
}, function(error, user) {
if (error) {
sails.log.error(error);
return res.redirect('errors/500', {});
}
else if (!user) {
// OAuthがキャンセルされた場合、error = null, user = falseになる
sails.log.verbose('OAuth Denied');
return res.redirect('/');
}
// セッションの再生成
req.session.regenerate(function(error) {
if (error) {
sails.log.error(error);
return res.redirect('/');
}
req.login(user, function(error) {
if (error) {
sails.log.error(error);
}
res.redirect('/'+redirectTo);
});
});
})(req, res);
}
詰まるポイント
上記の例はPassport0.2系だと動かない。0.2系で動かすにはさらに以下の2行を追加する必要がある。
passport0.2系の処理
req.session.regenerate(function(error) {
// この2行を追加
req.session.passport = {};
req._passport.session = req.session.passport;
req.login(user, function(error) {
session.regenerate()
はexpress-sessionの機能、req.login()
はpassportの機能で、実はこの2つにはモジュール間の関連があまりない。passportを使うときにはexpress middlewareにpassport.initialize
を追加しているはずだが、そこで初期化時にsessionオブジェクトに入れた値が、regenerate()
することにより消えてしまう。
0.3系ならreq.login()
時にその初期化処理を再度実行するような修正が入っていて、以下の2行は不要になっている。
というところの調査に半日費やし、GitHubで最新のコードを読むと修正が入ってたので0.3系にあげたら動いたという悲しい話。
ちなみにregenerate()
やlogin()
のタイミングではDBへのsession情報のInsertなどは実行されず、sessionオブジェクトに値を書き込んでいるだけ。レスポンスが返却されるときにデータは保存されるらしい。