logo

Next.js(AppRouter)でBASIC認証

2026-01-07
10 days ago

開発環境

  • next 16.1.1
  • react 19.2.3
  • react-dom 19.2.3

前提

  • Next.js の App Router を利用している
  • 本格的な認証(Auth.js など)までは不要
  • 個人運用のブログや管理画面など、自分しか使わない画面を簡易的に保護したいケースを想定

なお、この記事は「個人で運用しているブログの管理画面に最低限の認証をかけたい」と考え、BASIC 認証を Next.js(App Router)で簡単に実装できないか調べたことがきっかけでまとめています。

本題

Next.js(App Router)での BASIC 認証の考え方

Next.js の App Router では、proxy.ts を使って すべてのリクエストに対して認証チェックを行うことができます。

今回の構成では、

  • 認証チェック用の proxy 関数を用意
  • 認証に失敗した場合は /api/auth にリライト
  • /api/auth401 Unauthorized + WWW-Authenticate ヘッダーを返す

というシンプルな流れを採用しています。

【実装例】認証チェック(proxy.ts)

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

export function proxy(req: NextRequest) {
  // 開発環境では認証をスキップ
  if (process.env.NODE_ENV === 'development') {
    return NextResponse.next();
  }

  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_ID && pwd === process.env.BASIC_PWD) {
      return NextResponse.next();
    }
  }

  url.pathname = '/api/auth';

  return NextResponse.rewrite(url);
}

export const config = {
  matcher: ['/:path*'],
};
proxy.ts

ポイントは以下です。

  • authorization ヘッダーから BASIC 認証情報を取得
  • BASIC_ID / BASIC_PWD を .env で管理
  • 認証失敗時はページ遷移ではなく rewrite で認証用 API に誘導
  • 開発環境では認証が不要なのでスキップ

【実装例】認証用 API

import { NextResponse } from 'next/server';

export async function GET() {
  return new NextResponse('Unauthorized', {
    status: 401,
    headers: {
      'WWW-Authenticate': 'Basic realm="Secure Area"',
    },
  });
}
app/api/auth/route.ts

WWW-Authenticate ヘッダーを返すことで、ブラウザが自動的に BASIC 認証ダイアログを表示してくれます。

【実装例】環境変数

BASIC_ID=user
BASIC_PWD=password

ID・パスワードは必ず環境変数で管理してください。

この実装のメリット

  • 実装が非常にシンプル
  • 外部ライブラリ不要
  • 管理画面・検証環境の簡易な保護には十分

さいごに

Next.js(App Router)での BASIC 認証は、思っている以上に簡単に導入できます。

  • 個人ブログの管理画面
  • 一時的な検証用ページ
  • 社内向けの簡易ツール

といった用途であれば、BASIC 認証だけで十分なケースも多いです。

「本格的な認証を入れるほどではないが、誰でも見られるのは困る」

そんな場面では、今回のような実装を選択肢の一つとして検討してみてください。

参照