Advanced

Claude Codeでロールベースアクセス制御(RBAC)を実装する

Claude Codeを使ったRBACの設計と実装パターンを解説。権限管理、ミドルウェア設計、データベーススキーマまで実践的なコード付き。

ロールベースアクセス制御とは

RBAC(Role-Based Access Control)はユーザーにロールを割り当て、ロールごとに操作権限を定義するアクセス制御モデルです。Claude Codeを活用すれば、複雑な権限構造も体系的に実装できます。

権限モデルの設計

// 権限の定義
const PERMISSIONS = {
  "posts:read": "記事の閲覧",
  "posts:create": "記事の作成",
  "posts:update": "記事の編集",
  "posts:delete": "記事の削除",
  "users:read": "ユーザー情報の閲覧",
  "users:manage": "ユーザーの管理",
  "settings:manage": "設定の管理",
} as const;

type Permission = keyof typeof PERMISSIONS;

// ロールと権限のマッピング
const ROLE_PERMISSIONS: Record<string, Permission[]> = {
  viewer: ["posts:read"],
  editor: ["posts:read", "posts:create", "posts:update"],
  admin: [
    "posts:read",
    "posts:create",
    "posts:update",
    "posts:delete",
    "users:read",
    "users:manage",
  ],
  superadmin: Object.keys(PERMISSIONS) as Permission[],
};

データベーススキーマ(Prisma)

model User {
  id        String   @id @default(cuid())
  email     String   @unique
  name      String
  roles     UserRole[]
  createdAt DateTime @default(now())
}

model Role {
  id          String       @id @default(cuid())
  name        String       @unique
  permissions Permission[]
  users       UserRole[]
}

model Permission {
  id     String @id @default(cuid())
  name   String @unique
  roles  Role[]
}

model UserRole {
  user   User   @relation(fields: [userId], references: [id])
  userId String
  role   Role   @relation(fields: [roleId], references: [id])
  roleId String

  @@id([userId, roleId])
}

認可ミドルウェア

import { Request, Response, NextFunction } from "express";

function requirePermission(...requiredPermissions: Permission[]) {
  return async (req: Request, res: Response, next: NextFunction) => {
    const user = req.user;
    if (!user) {
      return res.status(401).json({ error: "Authentication required" });
    }

    const userPermissions = await getUserPermissions(user.id);

    const hasPermission = requiredPermissions.every((perm) =>
      userPermissions.includes(perm)
    );

    if (!hasPermission) {
      return res.status(403).json({
        error: "Insufficient permissions",
        required: requiredPermissions,
      });
    }

    next();
  };
}

async function getUserPermissions(userId: string): Promise<Permission[]> {
  const user = await prisma.user.findUnique({
    where: { id: userId },
    include: {
      roles: {
        include: {
          role: {
            include: { permissions: true },
          },
        },
      },
    },
  });

  if (!user) return [];

  const permissions = new Set<Permission>();
  for (const userRole of user.roles) {
    for (const perm of userRole.role.permissions) {
      permissions.add(perm.name as Permission);
    }
  }

  return Array.from(permissions);
}

APIルートへの適用

const router = express.Router();

// 閲覧は全ロール可
router.get("/posts", requirePermission("posts:read"), listPosts);

// 作成はeditor以上
router.post("/posts", requirePermission("posts:create"), createPost);

// 削除はadmin以上
router.delete(
  "/posts/:id",
  requirePermission("posts:delete"),
  deletePost
);

// ユーザー管理はadmin以上
router.get(
  "/users",
  requirePermission("users:read"),
  listUsers
);

router.put(
  "/users/:id/roles",
  requirePermission("users:manage"),
  updateUserRoles
);

フロントエンドの権限チェック

import { createContext, useContext, ReactNode } from "react";

interface AuthContextType {
  user: User | null;
  permissions: Permission[];
  hasPermission: (perm: Permission) => boolean;
  hasAnyPermission: (...perms: Permission[]) => boolean;
}

const AuthContext = createContext<AuthContextType | null>(null);

function PermissionGate({
  permission,
  children,
  fallback = null,
}: {
  permission: Permission;
  children: ReactNode;
  fallback?: ReactNode;
}) {
  const { hasPermission } = useContext(AuthContext)!;

  if (!hasPermission(permission)) {
    return <>{fallback}</>;
  }

  return <>{children}</>;
}

// 使用例
function PostActions({ postId }: { postId: string }) {
  return (
    <div>
      <PermissionGate permission="posts:update">
        <EditButton postId={postId} />
      </PermissionGate>
      <PermissionGate permission="posts:delete">
        <DeleteButton postId={postId} />
      </PermissionGate>
    </div>
  );
}

Claude Codeでの実装

RBACの実装をClaude Codeに依頼する際は、既存の認証基盤との統合を明示しましょう。認証の基本についてはJWT認証パターン、データベース設計についてはPrisma ORM完全ガイドも参照してください。

RBACを実装して。
- ロール: viewer, editor, admin, superadmin
- Prismaでスキーマ定義
- Express ミドルウェアで権限チェック
- React側にPermissionGateコンポーネントも作って

RBACの設計原則についてはNIST RBAC モデルが参考になります。Claude Codeの詳細は公式ドキュメントを確認してください。

まとめ

RBACは権限管理の基盤として多くのアプリケーションで必要になります。Claude Codeを使えば、バックエンドからフロントエンドまで一貫した権限管理を素早く構築できます。

#Claude Code #RBAC #認可 #セキュリティ #設計パターン