NextAuthを利用した保護されたルートの設定

힘센캥거루
2025년 1월 3일
3
107

今日はNextAuthを利用した保護されたルートの設定を学んでみましょう。

実際、この記事に関する情報がバラバラで苦労しました。

まずはできる限り公式ドキュメントを使って書いてみます。

1. この記事を書くことにした理由

NextAuthを利用した保護されたルートの設定-1

NextAuthを利用してログインは実装しました。

問題は、ルート保護とリダイレクトを一緒に使いたい場合でした。

ログインしていないユーザーでも、ログインしたユーザーでもルートパス「/」にアクセスしたときに「/category」へリダイレクトしたかったのです。

さらにログイン済みの人には「/profile」や「/login」へのアクセスをブロックしたかったのです。

しかし、これに関する記事もあまりなく、ChatGPTもずっと変なことばかり言うのでとてもイライラしました。

2. NextAuth公式ドキュメント

NextAuthを利用した保護されたルートの設定-2

結局、検索と公式ドキュメントで解決しました。

やはり公式ドキュメントは良いです。

このリンクにアクセスすると、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. 機能を実装する

NextAuthを利用した保護されたルートの設定-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. 後記

NextAuthを利用した保護されたルートの設定-4

最近のウェブ開発のトレンドについていくことが一般人には簡単ではないと再び感じました。

Expressはすでにデータが豊富で、AIに入力すればすぐにコードが作成されますが、Next.jsはそうではありません。

RedditやStack OverflowでもAIが最新のトレンドについていけていないという後記が多いようです。

それで、開発者がまだ(?)必要なのかもしれません。

英語力を伸ばして公式ドキュメントを一生懸命読んでみる必要がありそうです。

관련 글

Next.js フルスタックブログ開発記
Next.js フルスタックブログ開発記
Web開発に初めて触れてから1年ほど経った頃、自分だけのブログを持ちたいと思うようになった。そこで、およそ6か月これだけにかかりきりになって作ってみることにした。フロントエンド側の機能については、下記のキム・ドヒョンさんのブログを参考にするだけで十分だと思う。自分も mdx を使ってブログを作るだけ...
Caddyを利用した Next.js 無停止デプロイ(ローカルサーバー)
Caddyを利用した Next.js 無停止デプロイ(ローカルサーバー)
ホームページに何かをちょこちょこ載せたくなるたびにビルドしていたら、そのタイミング에 가끔 접속하는人がいるようだった。そうしているうちに、サーチコンソールでスコアがどんどん下がる現象が起きた。このままではまずいと思い、無停止デプロイをする方法を考えてみることにした。1. プロジェクトフォルダ2つ+...
Google検索インデックスの自動化 - Web Search Indexing API
Google検索インデックスの自動化 - Web Search Indexing API
前回の IndexNow に続いて、Google でも自動化してみることにした。調べてみると、Google は API として Web Search Indexing というものを提供していた。1. 対象範囲公式にこの API がサポートしている範囲は、求人情報とストリーミング動画サービスである。リ...
検索インデックス生成の自動化 - IndexNow
検索インデックス生成の自動化 - IndexNow
Bingにサイト登録をしている途中で知ったのだが、Bingでは IndexNow という機能を提供している。ポイントは、APIキーを使って、記事を書いた直後にすぐインデックス作成リクエストを飛ばせるということ。下のようなリクエストを fetch で作り、投稿機能に連動させておけば、記事をDBに保存す...
Nextjs、React サーバーがハッキングされた経験
Nextjs、React サーバーがハッキングされた経験
最初にセキュリティ問題に気づいたのは、12月5日の未明だった。React で認証なしにリモートコード実行が可能だということ。そのニュースを見て他の人には共有したものの、自分は大丈夫だろうと思って特に気にも留めなかった。1. ハッキングの痕跡を発見ところが、ブログのコードを更新しようとアクセスしてみる...
ブログに多言語機能を追加する(NextJS・next-intl・Vercel AI SDK)
ブログに多言語機能を追加する(NextJS・next-intl・Vercel AI SDK)
最近、ブログに多言語対応機能が必要だと感じた。そこで next-intl を使って多言語サービスを実装してみることにした。1.i18nまず多言語サービスを行うときには、守るべき原則がある。これを internationalization と呼ぶが、かなり長いので、先頭の i と末尾の n、そしてその...

댓글을 불러오는 중...