💩

【Passport.js】シリアライザーの挙動を調べる

2022/05/03に公開

Node.jsExpress を用いてログイン機能を実装しました。
そこで、passport, passport-local を用いたのですが、その挙動の流れが難しかったのでメモ。

serializeUser, deserializeUser, LocalStrategy たちが何をしているのかを確認します。

結論

  1. LocalStrategyが起動し、ユーザー情報を取得
  2. serializeUserでセッションにユーザー情報を格納
  3. deserializeUserでセッションからユーザー情報を取得
  4. 毎度 deserializeUserが動くことで、ログイン状態が保持される

コード

routes/auth.js
...
const passport = require('passport');
const LocalStrategy = require('passport-local');
const cookieSession = require("cookie-session");
...

passport.use(new LocalStrategy(function verify(username, password, cb) {
  client
    .query('SELECT * FROM users WHERE username = $1', [username])
    .then(results => {
      if (results.rows.length === 0) {
        console.log('Results is empty. Login failed');
        return cb(null, false);
      }
      if (results.rows[0].password !== password) {
        console.log('Password wrong. Login failed');
        return cb(null, false);
      }
      console.log('LocalStrategy called!', results.rows[0]);
      return cb(null, results.rows[0]);
    })
    .catch(e => {
      return cb(err);
    })
}));

passport.serializeUser(function(user, cb) {
  process.nextTick(function() {
    console.log('serializer called!', user);
    cb(null, { id: user.id, username: user.username });
  });
});

passport.deserializeUser(function(user, cb) {
  console.log('deserializer called!', user);
  process.nextTick(function() {
    return cb(null, user);
  });
});

router.use(
  cookieSession({
    name: "session",
    keys: ['keys'],
    maxAge: 24 * 60 * 60 * 1000,
  })
);
router.use(passport.session());

router.post('/login/password', passport.authenticate('local', {
  successRedirect: '/images',
  failureRedirect: '/login'
}));
...

ログ

ログイン処理のログです。
まず、LocalStrategy が呼ばれ、認証ロジックが稼働しています。
次に、serializeUser にてセッションにユーザー情報が格納されています。

あとは、ページ読み込みのたびに、deserializeUser が呼ばれています。毎回、セッションからユーザー情報を取得しています。

LocalStrategy called! { id: 1, username: 'a', password: 'a' }
serializer called! { id: 1, username: 'a', password: 'a' }

...

deserializer called! { id: 1, username: 'a' }

...

参考
https://zenn.dev/wkb/books/node-tutorial/viewer/todo_10#セッションを設定しよう

https://knimon-software.github.io/www.passportjs.org/guide/configure/

https://www.passportjs.org/tutorials/password/session/

Discussion