🔐

【Next.js】Next.js 15でBasic認証を実装する

に公開

先日、業務で「next側でBasic認証を掛けれるか」という要望があり実装しましたのでそれをメモとして残していこうと思います

実装方法

以下の手順で実装していきます

環境変数の作成

今回は「ステージング環境のみ掛けたい」という要件でしたのでステージング用の.env.stagingを作成

.env.staging
BASIC_FLAG=true
BASIC_USERNAME=username
BASIC_PASSWORD=password

middleware.tsの作成

Next.jsではmiddleware.tsを使用してBasic認証を実装するため、src直下に作成
中身は以下のように定義していきます

middleware.ts
import { NextRequest, NextResponse } from "next/server";

export const config = {
  matcher: "/:path*",
};

export function middleware(req: NextRequest) {
  // 認証を有効にするかどうか判定
  if (process.env.BASIC_FLAG && process.env.BASIC_FLAG !== "true") {
    return NextResponse.next();
  }

  // 環境変数の設定がなければスキップ
  if (
    process.env.BASIC_USERNAME === undefined ||
    process.env.BASIC_PASSWORD === undefined
  ) {
    return NextResponse.next();
  }

  // BASIC認証のチェック
  const hasBasic = req.headers.get("authorization");

  if (hasBasic) {
    const authValue = hasBasic.split(" ")[1];
    const [username, password] = Buffer.from(authValue, "base64")
      .toString()
      .split(":");
    if (
      username === process.env.BASIC_USERNAME &&
      password === process.env.BASIC_PASSWORD
    ) {
      // 認証成功
      return NextResponse.next();
    }
  }
    
  // 認証失敗
  return NextResponse.json(
    { error: "Basic Auth Required" },
    {
      headers: { "WWW-Authenticate": 'Basic realm="Secure Area"' },
      status: 401,
    }
  );
}

middleware.tsを作成後ステージング環境に.env.stagingを読みこましてデプロイして完了です
※ローカルで確認する場合は.env.local.env.stagingと同じ内容を記述して認証がかかっているかチェックします

コード詳細

matcher

matcherに定義するパスはmiddlewareを動かす対象のパスを指定します
ここではアプリ全体にかけたかったのでワイルドカードで指定しています
対象ページが複数ある場合は以下のように配列で指定することで可能です

export const config = {
  matcher: ['/about/:path*', '/dashboard/:path*'],
};

ヘッダの確認

authorizationを見て認証をチェック

const hasBasic = req.headers.get("authorization");

入力された値のチェック

authValueに入力された値が入るのでそれをエンコードし、整形したあと環境変数で定義した値と合っているかどうかチェックします

const authValue = hasBasic.split(" ")[1];
const [username, password] = Buffer.from(authValue, "base64")
    .toString()
    .split(":");

まとめ

Next.jsでのBasic認証の実装方法を紹介しました。
個人開発で学ぶこともありますがやはり実務でないと得られない知識があるのでこれからも恐れず学んでいきたいと思います(?)

参考

以下の記事を参考に書かせていただきました
https://zenn.dev/kiwichan101kg/articles/4fca756c3e02ae

Discussion