🔑
Next.jsのApp RouterでBasic 認証を実装する
開発時はだいたいBasic認証機能をつけることが多いのですが、
PagesRouterとAppRouterでAPIの作り方が異なるので備忘録として残します。
.env
BASIC_AUTH_USER="user"
BASIC_AUTH_PASSWORD="password"
middleware.ts
middleware.ts
は、PagesRouter・AppRouterで共通のものを利用できます。
/middleware.ts
import { NextRequest, NextResponse } from 'next/server';
export const config = {
matcher: ['/:path*'],
};
export function middleware(req: NextRequest) {
// 開発時では認証をスキップ
if (process.env.NODE_ENV === 'development') {
return NextResponse.next();
}
// 環境変数が設定されていない場合は認証をスキップ
if (!process.env.BASIC_AUTH_PASSWORD) {
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_AUTH_USER &&
pwd === process.env.BASIC_AUTH_PASSWORD
) {
return NextResponse.next();
}
}
url.pathname = '/api/basic-auth';
return NextResponse.rewrite(url);
}
AppRouterの場合
/app/api/basic-auth/route.ts
を作成して下記を入力します。
/app/api/basic-auth/route.ts
import { NextResponse } from 'next/server';
export async function GET() {
return NextResponse.json(
{ error: 'Basic Auth Required' },
{
status: 401,
headers: { 'WWW-Authenticate': "Basic realm='secure_area'" },
},
);
}
PagesRouterの場合
/pages/api/basic-auth.ts
を作成して下記を入力します。
/pages/api/basic-auth.ts
import type { NextApiRequest, NextApiResponse } from 'next';
export default function basicAuth(_: NextApiRequest, res: NextApiResponse) {
res.statusCode = 401;
res.setHeader('WWW-authenticate', "Basic realm='secure_area'");
res.end('Basic Auth Required');
}
Discussion