© TOOLS BOX — Next.js / React / TypeScript コードサンプル集

サンプルガイド
←サンプル一覧
nextjsauthentication

Next.js でロールベースの表示制御とアクセスガードを実装する

ユーザーのロール(admin / editor / viewer など)に応じて UI 要素の表示・非表示を制御し、Server Component で早期ガードするパターン。forbidden との責務の違いも示す。

難易度: 初級·更新: 2026-04-18

対応バージョン

nextjs 15react 19

前提環境

Next.js App Router の Server Component と認証フローの基本を理解していること

概要

ユーザーのロール(admin / editor / viewer)に基づいて UI 要素の表示・非表示を切り替え、権限のないページには forbidden() でアクセスを遮断する。Server Component でのガードと Client Component での表示制御の両方を実装し、forbidden() との責務の違いも示す。

インストール

# 追加インストールは不要

実装

ロール型とガードユーティリティ

// lib/auth.ts(抜粋)

export type UserRole = "admin" | "editor" | "viewer";

export type AuthUser = {
  id: string;
  name: string;
  role: UserRole;
};

/** 指定ロール以上の権限があるか確認する */
export function hasRole(user: AuthUser | null, required: UserRole): boolean {
  if (!user) return false;
  const hierarchy: UserRole[] = ["viewer", "editor", "admin"];
  return hierarchy.indexOf(user.role) >= hierarchy.indexOf(required);
}

Server Component でのページガード

// app/admin/page.tsx
import { forbidden } from "next/navigation";
import { getCurrentUser, hasRole } from "@/lib/auth";

export default async function AdminPage() {
  const user = await getCurrentUser();

  if (!user) {
    // 未ログイン → forbidden または redirect
    forbidden();
  }

  if (!hasRole(user, "admin")) {
    // ログイン済みだが admin 未満 → 403
    forbidden();
  }

  return (
    <div>
      <h1>管理者ページ</h1>
      {/* ...管理コンテンツ */}
    </div>
  );
}

Server Component での UI 要素制御

// app/samples/[slug]/page.tsx(抜粋)
import { getCurrentUser, hasRole } from "@/lib/auth";

export default async function SampleDetailPage({ params }: Props) {
  const { slug } = await params;
  const user = await getCurrentUser();

  return (
    <div>
      <h1>{slug}</h1>

      {/* editor 以上のみ編集ボタンを表示 */}
      {hasRole(user, "editor") && (
        <a
          href={`/admin/samples/${slug}/edit`}
          className="rounded bg-gray-100 px-3 py-1 text-sm hover:bg-gray-200"
        >
          編集
        </a>
      )}

      {/* admin のみ削除ボタンを表示 */}
      {hasRole(user, "admin") && (
        <button
          className="rounded bg-red-100 px-3 py-1 text-sm text-red-700 hover:bg-red-200"
        >
          削除
        </button>
      )}
    </div>
  );
}

Client Component でのロールガード

// components/RoleGuard.tsx
"use client";

type Props = {
  role: string;
  required: "admin" | "editor" | "viewer";
  children: React.ReactNode;
  fallback?: React.ReactNode;
};

const HIERARCHY = ["viewer", "editor", "admin"] as const;

export function RoleGuard({ role, required, children, fallback = null }: Props) {
  const hasAccess =
    HIERARCHY.indexOf(role as (typeof HIERARCHY)[number]) >=
    HIERARCHY.indexOf(required);

  return hasAccess ? <>{children}</> : <>{fallback}</>;
}
// 使用例
<RoleGuard role={user.role} required="editor">
  <button>編集</button>
</RoleGuard>

<RoleGuard role={user.role} required="admin" fallback={<p>権限がありません</p>}>
  <AdminPanel />
</RoleGuard>

forbidden() と UI 制御の使い分け

状況手段
ページ自体へのアクセスを完全に拒否forbidden()
ページは表示するが一部 UI を隠すhasRole() 条件分岐
Client Component でロール条件分岐RoleGuard コンポーネント

ポイント

  • hasRole にロール階層(viewer < editor < admin)を持たせることで、「editor 以上」という条件を単一の関数で表現できる
  • Server Component のガードは forbidden() を使い、ページ単位でブロックする。UI 要素レベルの制御は hasRole() 条件分岐で行い、責務を分ける
  • RoleGuard を Client Component として実装することで、user.role を props で受け取りツリー内で任意に再利用できる
  • Server Component ではロールチェックをレンダリング時に行えるため、Client Component よりも条件が確実に適用される。重要な制御は Server Component 側で行う
  • fallback を null にすることで、権限不足の場合に何も表示しないデフォルト動作を実現できる

注意点

nextjs-forbidden-page はリソース単位の 403。nextjs-unauthorized-page は認証済みでロール不足の 401/403。nextjs-protected-layout は layout 単位の一括保護。これはロール別の UI 要素表示制御と Server Component での早期ガードに特化。

関連サンプル

同じテーマや技術スタックを使った実装例

  • Next.js で認証状態に応じてページを redirect する

    Server Component や Route Handler でセッションの有無を確認し、認証済みユーザーをダッシュボードへ、未認証ユーザーをログインページへ redirect するパターンの例。

  • Next.js で権限不足(forbidden)時の専用ページを表示する

    認証済みで操作は許可されているが特定リソースへのアクセス権限がない場合に forbidden ページを表示し、unauthorized との使い分けを示す例。

  • Next.js で権限不足(unauthorized)時の専用ページを表示する

    認証済みだが権限が不足しているユーザーに unauthorized ページを表示し、適切なメッセージと導線を提供するパターン。Next.js の unauthorized() 関数と not-found の使い分けを示す例。

  • Next.js App Router の layout で認証チェックして配下ページを保護する

    App Router の layout.tsx でセッション Cookie を確認し、未認証ユーザーをログインページへ redirect することで配下のすべてのページを一括保護する例。

  • Next.js Middleware で未認証ユーザーをリダイレクトする

    middleware.ts でリクエスト時に Cookie をチェックし、未認証ユーザーをログインページへリダイレクトするルート保護の実装例。

関連仕様

このサンプルを理解するのに役立つ仕様や概念

  • FrameworkNext.jsReact ベースのフルスタックフレームワーク。SSR・SSG・App Router・API Routes を提供する。
←サンプル一覧に戻る