👋

Next.jsのmiddlewareでbasic認証実装(React v18)

2022/08/22に公開1

結構いろいろな記事が上がっているが、React v18だとmiddlewareが反応しないパターンが多かったため、メモ

結論api routesを使う

  1. .envに環境変数を設定
  2. middlewareを実装(プロジェクト全体に反映させる為には、pages配下ではなく、ルート配下に書く必要があるらしい、この辺はまりました、、、、)
middleware.ts
import { NextRequest, NextResponse } from "next/server";

export const config = {
  matcher: ["/", "/index"]
};

export function middleware(req: NextRequest) {
  const basicAuth = req.headers.get("authorization");
  const url = req.nextUrl;

  if (basicAuth) {
    const authValue = basicAuth.split(" ")[1];
    const [user, pwd] = atob(authValue).split(":");

    if (user === process.env.BASIC_AUTH_USER && pwd === process.env.BASIC_AUTH_PASSWORD) {
      return NextResponse.next();
    }
  }
  url.pathname = "/api/auth";

  return NextResponse.rewrite(url);
}

  1. api routesで受け取る
pages/api/auth.ts
import type { NextApiRequest, NextApiResponse } from "next";

export default function handler(_: NextApiRequest, res: NextApiResponse) {
  res.setHeader("WWW-authenticate", 'Basic realm="Secure Area"');
  res.statusCode = 401;
  res.end(`Auth Required.`);
}

これでいける。

Discussion

nap5nap5

記事の内容を生かしつつデモを作ってみました。

このドキュメントを参考にしてみました。
https://nextjs.org/docs/messages/invalid-route-source

Publicにアクセス必要なページサンプル
https://zi6fxj-3000.preview.csb.app/feedback/general

Basic認証が必要なページサンプル
https://zi6fxj-3000.preview.csb.app

BASIC_AUTH_USER="Violet"
BASIC_AUTH_PASSWORD="Gilbert"

https://codesandbox.io/p/sandbox/brave-bush-zi6fxj?file=%2FREADME.md&selection=[{"endColumn"%3A95%2C"endLineNumber"%3A2%2C"startColumn"%3A95%2C"startLineNumber"%3A2}]

簡単ですが、以上です。