Next.jsのMiddlewareは、リクエストが完了する前にコードを実行する機能である。今回は、リクエストが完了する前にユーザーの認証状態をチェックし、未認証の場合はログイン画面にリダイレクトさせる処理を実装した。

私はAWS Amplifyを使用してアプリケーションを開発しているが、aws-amplifyを使用していない場合でも、Middlewareの使用方法などは共通しているため参考になるかと思う。

開発環境

"next": "14.0.3",
"aws-amplify": "^6.0.3",
"typescript": "^5"

実装

プロジェクトのルートから、以下のファイルを用意する。

- src/utils/server-utils.ts 
- src/middleware.ts

作成したファイルはそれぞれ以下の役割を持つ。

  • server-utils.ts: ミドルウェア内の RunWithAmplifyServerContext を使用して、Amplify API を操作することができるようにする共通処理。
  • middleware.ts: リクエスト前に実行したい処理を記述。

server-utils.ts

import { createServerRunner } from "@aws-amplify/adapter-nextjs";
import config from "@/amplifyconfiguration.json";

export const { runWithAmplifyServerContext } = createServerRunner({
  config,
});

middleware.ts

import { runWithAmplifyServerContext } from "@/utils/server-utils";
import { fetchAuthSession } from "aws-amplify/auth/server";
import { NextRequest, NextResponse } from "next/server";

export async function middleware(request: NextRequest) {
  const response = NextResponse.next();

  // 認証チェック
  const authenticated = await runWithAmplifyServerContext({
    nextServerContext: { request, response },
    operation: async (contextSpec) => {
      try {
        // 認証情報を取得
        const session = await fetchAuthSession(contextSpec, {});
        return session.tokens !== undefined;
      } catch (error) {
        console.log(error);
        return false;
      }
    },
  });

  // ユーザーが認証された場合、ルート要求は続行される
  if (authenticated) {
    return response;
  }

  // 未認証の場合はログイン画面にリダイレクト
  return NextResponse.redirect(new URL("/auth/login", request.url));
}

上記の実装により、未認証の場合はログイン画面にリダイレクトされるようになる。

その他の機能

パスマッチング

特定のパスにマッチした場合に一括で処理を実行したい場合、以下の記述を末尾に追加する。

// パスマッチング: '/user/:path*' は /user 以下のすべてのパスにマッチする
export const config = {
  matcher: "/user/:path*",
};

参照ソース

https://nextjs.org/docs/pages/building-your-application/routing/middleware

https://aws.amazon.com/jp/blogs/news/amplify-javascript-v6/

カテゴリー: Next.js