🎉

Next.js 13とApp RouterでBasic認証を実装する

2023/09/09に公開

はじめに

開発中のサービスに対してBasic認証を設定したい、なんてことがあるかもしれません。
この記事では、Next.jsとApp RouterでBasic認証を実装する方法を共有します。

環境

  • Next.js 13.4.8
  • React 18.2.0

方針

Basic認証は Middleware を使用して実現できます。公式のサンプル実装にBasic認証の実装事例があるので参考にします。

https://github.com/vercel/examples/tree/main/edge-middleware/basic-auth-password

このサンプルはPages Routerで実装されているためApp Routerで利用できるように調整します。

実装

src/middleware.ts

サンプルの middleware.ts を参考に実装します。

実装についてはPages Routerで使っているものをそのまま使うことができます。ただし、App Routerの場合は src 配下に実装する必要があります。

参考: Routing: Middleware - convention | Next.js

また、今回は全てのパスに対してBasic認証を実施したかったため、matcherによるパスの指定を削除します。

src/middleware.ts
import type { NextRequest } from 'next/server';
import { NextResponse } from 'next/server';

function middleware(req: NextRequest): NextResponse {
  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.NEXT_PUBLIC_BASIC_AUTH_USER &&
      pwd === process.env.NEXT_PUBLIC_BASIC_AUTH_PASSWORD
    ) {
      return NextResponse.next();
    }
  }
  url.pathname = '/api/basic-auth';

  return NextResponse.rewrite(url);
}

export { middleware };

src/app/api/basic-auth/route.ts

サンプルの pages/api/auth.ts を参考に実装していきます。

App Routerでは src/app/api/basic-auth/route.ts に実装を行います。

src/app/api/basic-auth/route.ts
import { NextResponse } from 'next/server';

const GET = (): NextResponse => {
  return NextResponse.json(
    { error: 'Basic Auth Required' },
    {
      status: 401,
      headers: { 'WWW-Authenticate': "Basic realm='secure_area'" },
    },
  );
};

export { GET };

これで、ページを開いたタイミングでBasic認証が動作するようになります。

(おまけ) 本当にBasic認証は必要?

Basic認証を実装する前に、本当にBasic認証が必要か?という観点で考えることは必要だと思います。
ホスティングしているサービスが提供する認証機能を利用できるかもしれません。

例えば、Vercelの場合は Vercel Authentication を利用して認証をかけることができます。Hobby~Proプランで設定が可能なのはPreview環境までで、Production環境にも設定を行うにはEnterpriseプランに契約をするかProプランで追加費用を支払う必要があります。これについては本番環境へのデプロイを制限する、などの運用でカバーも検討できます。

取れるセキュリティリスクと環境を考慮してバランスの取れた選択をしていきたいところです。

最後に

今回はNext.js+App RouterでBasic認証を設定しました。
Next.jsやApp Routerについてはキャッチアップをし始めたばかりで手探り状態ですが、今後も引き続きキャッチアップをしていきます。

参考

https://github.com/vercel/examples/tree/main/edge-middleware/basic-auth-password
https://nextjs.org/docs/app/building-your-application/routing/middleware
https://zenn.dev/rabbit/articles/b7d712a2f1287f
https://zenn.dev/hayato94087/articles/85095219de0e9b

Discussion