概要

Cross-Site Request Forgery(CSRF)攻撃を防ぐために、Next.jsでCSRFトークンを実装する方法を解説します。CSRF攻撃は、悪意のあるウェブサイトがユーザーに気づかれないままリクエストを送信させる攻撃です。これを防ぐために、状態を変更するAPIリクエストにはCSRFトークンを含め、サーバーがその正当性を検証する必要があります。

CSRFトークンの仕組み

CSRFトークンは、サーバーが知っているシークレットキーを基に生成され、ユーザーのセッションに紐付けられます。トークンは次のような手順で生成・検証されます。

  1. トークン生成: サーバーはシークレットとソルトを組み合わせ、クライアントに返すトークンを生成します。
  2. クライアントのトークン送信: クライアントはこのトークンをリクエストのカスタムヘッダーとクッキーに含めて送信します。
  3. トークンの検証: サーバーは、送信されたトークンが正しいかどうかを検証し、一致すればリクエストを処理します。

実装手順

必要なライブラリのインストール

CSRFトークンをサポートするために、next-csrfのようなライブラリを使用します。以下はその設定方法の一例です。

npm install next-csrf

CSRFトークンのセットアップ

まず、環境変数にシークレットを設定します。

# .env.local
NEXT_CSRF_SECRET="your_random_secret_key"

次に、CSRFトークンの生成とAPI保護を行うlib/csrf.jsを作成します。

import { nextCsrf } from 'next-csrf';
const { csrf, setup } = nextCsrf({
    secret: process.env.NEXT_CSRF_SECRET,
});
export { csrf, setup };

APIルートの保護

APIルートにCSRFトークンを検証するミドルウェアを適用します。これにより、POSTやDELETEリクエストなど、セキュアな操作に対してCSRF保護が有効になります。

import { csrf } from '../../lib/csrf';
const handler = (req, res) => {
  return res.status(200).json({ message: "Protected API" });
};
export default csrf(handler);

フロントエンドでのトークン使用

トークンを含めてAPIにリクエストを送信する必要があります。ログインページなどのサーバーサイドレンダリング(SSR)ページでCSRFトークンを設定し、フォームの送信時にこのトークンを含めます。

import { setup } from '../lib/csrf';
export const getServerSideProps = setup(async ({ req, res }) => {
  return { props: {} };
});

このようにして、トークンが適切にクライアントにセットされ、送信されるようになります。

使用例と検証

CSRFトークンの動作を検証するには、クライアントが適切にトークンを送信し、それがサーバーで正しく検証されているかを確認します。curlを使ってテストすることも可能です。

curl -X POST http://localhost:3000/api/protected -H "X-CSRF-Token: your_token" --cookie "XSRF-TOKEN=your_cookie_token"

まとめ

CSRFトークンは、状態を変更するAPIリクエストに対する重要なセキュリティ対策です。Next.jsでは、next-csrfライブラリを使用して簡単にCSRFトークンを実装できます。APIルートを保護することで、セキュリティを強化し、悪意のあるリクエストからユーザーを守ることができます。