今日はNextAuthを利用した保護されたルートの設定を学んでみましょう。
実際、この記事に関する情報がバラバラで苦労しました。
まずはできる限り公式ドキュメントを使って書いてみます。
1. この記事を書くことにした理由

NextAuthを利用してログインは実装しました。
問題は、ルート保護とリダイレクトを一緒に使いたい場合でした。
ログインしていないユーザーでも、ログインしたユーザーでもルートパス「/」にアクセスしたときに「/category」へリダイレクトしたかったのです。
さらにログイン済みの人には「/profile」や「/login」へのアクセスをブロックしたかったのです。
しかし、これに関する記事もあまりなく、ChatGPTもずっと変なことばかり言うのでとてもイライラしました。
2. NextAuth公式ドキュメント

結局、検索と公式ドキュメントで解決しました。
やはり公式ドキュメントは良いです。
このリンクにアクセスすると、NextAuthとmiddlewareをどのように組み合わせて利用するかが載っています。
import { withAuth } from "next-auth/middleware";
export default withAuth(
// `withAuth` augments your `Request` with the user's token.
function middleware(req) {
console.log(req.nextauth.token);
},
{
callbacks: {
authorized: ({ token }) => token?.role === "admin",
},
}
);
export const config = { matcher: ["/admin"] };
ここでのポイントは、middlewareをwithAuthで包むとリクエストのトークンにアクセスできるということです。
トークンが不要であれば、middleware内で処理し、authorizedが必要であればcallbacksに渡して処理すれば良いです。
middlewareでも処理は可能なので、わざわざcallbackで渡さなくても問題ないかもしれません。
3. 機能を実装する

これを応用してみましょう。
withAuthでmiddlewareを包みます。
簡略化するとwithAuth(middleware, callbacks: {})という形式です。
リクエストが来ると、まずミドルウェアで処理し、次へ渡します。
まずコードから見てみましょう。
import { withAuth } from "next-auth/middleware";
import { NextResponse } from "next/server";
// withAuthで包んだミドルウェアをexport
export default withAuth(
function middleware(req) {
// ルートURL(/)へのアクセス時に/categoryへリダイレクト
if (req.nextUrl.pathname === "/") {
return NextResponse.redirect(new URL("/category", req.url));
}
if (
req.nextauth.token?.authLevel !== "admin" &&
req.nextUrl.pathname.startsWith("/dashboard")
) {
return NextResponse.redirect(new URL("/category", req.url));
}
return NextResponse.next();
},
{
callbacks: {
authorized: ({ token, req }) => {
// dashboard権限チェック
// profileで始まるパスのみ認証検査
if (req.nextUrl.pathname.startsWith("/profile")) {
return !!token;
}
// その他のパスは常にtrueを返す
return true;
},
},
}
);
export const config = {
matcher: [
"/((?!api|_next/static|_next/image|.*\\.avif$).*)", // 静的ファイル除外
"/",
"/dashboard",
"/profile/:path*", // profileパスのみmatcherに含む
],
};
こうすると、すべてのユーザーが「/」にアクセスすると「/category」にリダイレクトされます。
ログインしたユーザーの中で権限が「admin」でないユーザーは「/dashboard」パスにアクセスするとリダイレクトされます。
また、ログインしていないユーザーが「/profile」にアクセスするとログイン画面が表示されます。
それ以外のことはトークンを操作すれば可能です。
4. 後記

最近のウェブ開発のトレンドについていくことが一般人には簡単ではないと再び感じました。
Expressはすでにデータが豊富で、AIに入力すればすぐにコードが作成されますが、Next.jsはそうではありません。
RedditやStack OverflowでもAIが最新のトレンドについていけていないという後記が多いようです。
それで、開発者がまだ(?)必要なのかもしれません。
英語力を伸ばして公式ドキュメントを一生懸命読んでみる必要がありそうです。
댓글을 불러오는 중...