Next.js、next-iron-sessionでのセッション管理（ログインユーザー管理の例）

まずインストール

<ol>
<li>npm add next-iron-session
<br>→必須。サーバーサイドのセッション管理用
</li>
<li>npm install serverless-mysql
<br>→MySQL実行用。ユーザ認証方法によってはいらない。
</li>
<li>npm i sql-template-strings
<br>→MySQLのセキュリティ用（インジェクション防止）</li>
</ol>

まず、/libフォルダと、その中にsession.tsを作成。
（next-iron-sessionの公式のgitHubから流用）
/lib/session.ts

```
import { NextApiRequest, NextApiResponse } from "next";
import { Session, withIronSession } from "next-iron-session";

// optionally add stronger typing for next-specific implementation
export type NextIronRequest = NextApiRequest & { session: Session };
export type NextIronHandler = (
  req: NextIronRequest,
  res: NextApiResponse,
) => void | Promise<void>;

const withSession = (handler: NextIronHandler) =>
  withIronSession(handler, {
    password: process.env.SECRET_COOKIE_PASSWORD ?? '',
    cookieName: "next-iron-session/examples/next.js",
    cookieOptions: {
      // the next line allows to use the session in non-https environments like
      // Next.js dev mode (http://localhost:3000)
      secure: process.env.NODE_ENV === "production",
    },
  });

export default withSession;
```

ポイント
 １. 全体の構造として、
import { Session, withIronSession } from "next-iron-session";
でインポートした、withIronSessionに、
・handler(実際にapiとして処理を行いたい関数)
・sessionに関連するオプション
を渡しています。

handlerとなる関数は、通常のNext.jsのNode.jsのエンドポイント同様に、(req, res)の引数を受け取りますが、
（リクエスト, レスポンスの省略です。）
ここでのreqは NextIronRequestという型で、
本来のNextApiRequest型＋Sessionも保持しています。

このSessionの中を覗いてみると、

```
export type Session = {
  set: <T = any>(name: string, value: T) => T;
  get: <T = any>(name: string) => T | undefined;
  unset: (name: string) => void;
  destroy: () => void;
  save: () => Promise<string>;
};
```
このようにセッターやゲッター等、セッションの操作に使う関数が含まれていることがわかります。

これらを受けとったwithIronSessionを返す関数として、withSessionが作られ、エクスポートされることで実際に呼び出すapiで使用されます。（後述）


 ２. withIronSessionの第２引数として、セッションに関するオプションが用意されます。
他にも詳細な設定が可能ですので、next-iron-sessionの公式のドキュメントも参照してみてください。


password：env内で定義します。32文字以上のパスワードにする必要があるそうです。
cookieName：セッション情報と対になるクッキーの名称です。一応デバッグツール等を使うとユーザから見えるものになりますので、少し気を遣いましょう。
cookieOptions：保持時間など設定できますので、公式ドキュメントを見て必要なオプションを設定しましょう。




これらを呼び出し使用する、api側のファイルは以下のような感じです。
/api/login.ts

```

import withSession from '../../lib/session' //↑のファイルをインポート

const db = require('../../lib/mysql')
const escape = require('sql-template-strings')

type PostData = {
    email: string;
    password: string;
}

type UserData = {
    ...
}

export type QueryResult = {
    loginResult: UserData;
}

{
export default withSession(async (req, res) => {

    const postData: PostData = req.body;
    const queryResult = await db.query(escape`
    SELECT
        ...
    FROM
        USERS_LIST
    WHERE
        EMAIL = ${postData.email}
        AND PASSWORD = ${postData.password}
    `);

    let loginResult;
    if (queryResult) {
        req.session.set("SESSION_USER", queryResult[0]);
        await req.session.save();
        loginResult = queryResult[0];
    } else {
        loginResult = {};
    }
    res.status(200).json({ loginResult });
});

```

今回はMySQLのユーザーテーブルを使ってのログイン認証＋ユーザーログイン情報のセッション保持になっていますが、
そのほかの認証でも、next-iron-sessionのセッション保持機能を使えます。

ポイント
1.インポートしたwithSession関数の引数(handler)として、実行した関数を渡します。
この中で、

```
        req.session.set("SESSION_USER", queryResult[0]);
        await req.session.save();
```
とすることで、reqに含まれるsessionのセッターなどの関数が実行できます。
ここでは、req.session.set(キー, 値)を使ってセッションに値を保持しています。

この後、ユーザー情報をセッションから取得したい場合、

```
 const user = req.session.get("SESSION_USER") ? req.session.get("SESSION_USER") : {};
```
等として、ユーザー情報を取得できます。

```
    req.session.destroy();
```
とすると、セッションを破棄し、ログアウト時の処理も実装できます。

いずれも
export default withSession(async (req, res) => {})
の中で実行します。
必要に応じてapiを作成してください。



公式のgitHubなどを見れば、なんとなく使える人が多いとは思いますが、
日本語の記事は少ないので、Next.jsでサーバーサイドのセッション管理を行いたい方は参考にしてください。

以上です。