【Next.js】SSG(ISR)でも簡単にベーシック認証やverifyIdTokenを行う方法
2022-04-16
Middleware を使用すれば意外とあっさり組めちゃいます。
import fetchAdapter from "@vespaiach/axios-fetch-adapter";
import axios from "axios";
import { NextRequest, NextResponse } from "next/server";
async function middleware(req: NextRequest): Promise<Response> {
// revalidate 時またはファイルを参照している場合は全通しする
if (
req.headers.has("x-prerender-revalidate") ||
req.nextUrl.pathname.includes(".")
) {
return NextResponse.next();
}
/*
* ベーシック認証 start
*/
// api の場合は認証を行わない
if (!req.nextUrl.pathname.startsWith("/api")) {
const authRequiredResponse = new Response("Auth required", {
headers: {
"WWW-Authenticate": 'Basic realm="Secure Area"',
},
status: 401,
});
const basicAuth = req.headers.get("authorization");
if (!basicAuth) {
return authRequiredResponse;
}
const auth = basicAuth.split(" ")[1];
const [user, password] = Buffer.from(auth, "base64").toString().split(":");
if (
password !== process.env.BASIC_AUTH_PASSWORD ||
user !== process.env.BASIC_AUTH_USER
) {
return authRequiredResponse;
}
}
/*
* ベーシック認証 end
*/
/*
* verifyIdToken start
*/
// ログイン不要なページは verify を行わない
if (
req.nextUrl.pathname !== "/redirect" &&
req.nextUrl.pathname !== "/signin" &&
req.nextUrl.pathname !== "/signout"
) {
try {
const axiosInstance = axios.create({
adapter: fetchAdapter,
});
await axiosInstance.get(`${req.nextUrl.origin}/api/verifyIdToken`, {
headers: {
cookie: `idToken=${req.cookies.idToken}; refreshToken=${req.cookies.refreshToken}`,
},
});
return NextResponse.next();
} catch {
return NextResponse.redirect(`${req.nextUrl.origin}/signout`);
}
}
/*
* verifyIdToken end
*/
return NextResponse.next();
}
export default middleware;
ポイントは req.headers.has("x-prerender-revalidate") です。
この実装によって revalidate 時に認証を回避することが可能となります。Failed to revalidate route of a specific locale
ぜひ参考になりましたら幸いです。