JavaScript
Node.js
Koa

["Internal Server Error"との闘い] koa(koa-session,koa-passport)でユーザー登録ページ

koaフレームワークで、以下のミドルウェアとボディーパーサーを使用してセッションを使用したサイトを作成しています。
また、ユーザー管理DBはMongoDB(mongoose)を使用しています。

  • koa-session
  • koa-passport
  • koa-router
  • koa-static
  • async-busboy(ボディーパーサー)

ユーザー登録画面を作成において、使用済みIDチェックなどの処理は画面リロードなしで行うようFetch APIを使用しています。
特にユーザー登録に成功したときに、そのままサーバー側でログインした状態に移行したいなというときに、躓いたので備忘録としての投稿です。

ユーザー登録画面において、登録ボタン(signupButton)をクリックした際に、Fetch APIでPOSTリクエストを投げます。

クライアント
signupButton.onclick = async evt => {
    const res = await fetch('/signup', {
        method: 'POST',
        body: new FormData(signupForm)
    });
    const resText = await res.text();
    if(resText === 'exists') {
      // 使用済みID
    }
};
サーバー(Node.js)
router.post('/signup', async ctx => {
    const { fields } = await asyncBusboy(ctx.req);
    const id = fields.id;
    const pass = fields.pass;
    const confirmPass = fields.confirmPass;

    if (fields.id && fields.pass && fields.pass === fields.confirmPass) {
        try {
            // DB検索
            const user = await User.findOne({ id });
            if (user) {
                // 使用済みID
                ctx.body = 'exists';
            } else {
                // ユーザー登録
                const newUser = new User({ id, password });
                await newUser.save();
            }
        } catch (err) {
            // エラー
            ctx.body = 'error';
        }
    }
});

ここで、登録ボタンをクリックすると、ユーザー登録に成功したらそのまま自動的にログイン→ログイン後の画面に遷移したいと思い、コードを以下のように修正しました。

クライアント
// ...
    // 'success'だったら'/app'に遷移する処理追加
    if(resText === 'success') {
        location.href = '/app';  
    }
    if(resText === 'exists') {
      // 使用済みID
    }
// ...
サーバー(Node.js)
// ...
                // ユーザー登録
                const newUser = new User({ id, password });
                await newUser.save();
                await ctx.login(newUser); // passportのloginメソッドを実行し、ログイン状態に移行
                ctx.body = 'success'; // 'success'を返す
// ...

これでサーバー側でログイン済みの状態となるようですが、クライアント側は一応URLが'/app'になっているものの、Internal Server Errorと表示されてしまいます。
なぜかと調査すると、そう、クッキーが空のままなのです。
どうしたものかとひと悶着したのち、以下のようにFetch APIで一行付け足すだけで解決しました。

クライアント(ブラウザー)
// ...
    const res = await fetch('/signup', {
        method: 'POST',
        body: new FormData(signupForm),
        credentials: 'include' // ←これ追加
    });
// ...

これで、'/app'に遷移してもInternal Server Errorとならずにログイン後のページのコンテンツが表示されるようになりました。