みかづきブログ・カスタム

基本的にはちょちょいのほいです。

ミドルウェアを使ってNext.js(13.1.0以降)で作成したウェブサイトにBasic認証を設定する 🔐

かつて、Next.js 12でミドルウェアを使ったBasic認証の設定方法を 記事 にまとめましたが、Next.js 13になって、ミドルウェアの設定方法に微妙な変更があったため調査しました。

blog.kimizuka.org

nextjs.org

変更点

middleware.tsの位置変更

前回の方法 をそのまま使用すると、

error - Nested Middleware is not allowed, found:
pages/_middleware
Please move your code to a single file at /src/middleware instead.
Read More - https://nextjs.org/docs/messages/nested-middleware

と、エラーが表示されます。

nextjs.org

対応するためには、ミドルウェアの位置を pages/_middleware.ts から src/middleware.ts に移動する必要があります。

bufferモジュールの削除

pages/_middleware.ts から src/middleware.ts に移動し、ユーザー名、パスワードを入力すると、

error - Error: The edge runtime does not support Node.js 'buffer' module.
Learn More: https://nextjs.org/docs/messages/node-module-in-edge-runtime

と、エラーが表示されます。

nextjs.org

Node.jsのグローバルクラスが使えないので、Bufferを使うのを止め、atobに置き換えます。
つまり、

const [ user, password ] = Buffer.from(auth, 'base64').toString().split(':');

の部分を、

const [ user, password ] = atob(auth).split(':');

とします。

結論

src/middleaware.ts

import { NextRequest, NextResponse } from 'next/server';

const USER_NAME = 'user';
const PASSWORD = 'password';

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

  if (basicAuth) {
    const auth = basicAuth.split(' ')[1];
    const [ user, password ] = atob(auth).split(':');

    if (user === USER_NAME && password === PASSWORD) {
      return NextResponse.next();
    }
  }

  return new Response('Auth required', {
    status: 401,
    headers: {
      'WWW-Authenticate': 'Basic realm="Secure Area"'
    }
  });
}

こちらのコードを、src/middleaware.tsに設置すればBasic認証が掛かります。
実際に使用する場合は、USER_NAME、PASSWORDを、ファイルに直書きするのではなく、envファイルに書き込んだ方が安全です。