clerk-enterprise-rbac
エンタープライズSSO、ロールベースアクセス制御、組織管理を設定できます。SSO統合の実装、ロールベースの権限設定、組織レベルのコントロール構築に使用します。「clerk SSO」「clerk RBAC」「clerk enterprise」「clerk roles」「clerk permissions」「clerk SAML」などのフレーズで起動します。
description の原文を見る
Configure enterprise SSO, role-based access control, and organization management. Use when implementing SSO integration, configuring role-based permissions, or setting up organization-level controls. Trigger with phrases like "clerk SSO", "clerk RBAC", "clerk enterprise", "clerk roles", "clerk permissions", "clerk SAML".
SKILL.md 本文
Clerk Enterprise RBAC
概要
エンタープライズグレードのSSO、ロールベースアクセス制御、組織管理を実装します。
前提条件
- Clerk Enterprise ティアのサブスクリプション
- SAML/OIDCをサポートするID プロバイダー (IdP)
- ロールベースアクセスパターンの理解
- 組織構造が定義されていること
手順
ステップ 1: SAML SSO の設定
Clerk ダッシュボード内
- Configure > SSO Connections に移動
- SAML Connection を追加
- IdP 設定を設定:
- ACS URL:
https://clerk.yourapp.com/v1/saml - Entity ID: Clerk により提供
- SP メタデータをダウンロード
- ACS URL:
IdP 設定 (例: Okta)
<!-- SAML Attributes to map -->
<saml:Attribute Name="email">
<saml:AttributeValue>user.email</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="firstName">
<saml:AttributeValue>user.firstName</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="lastName">
<saml:AttributeValue>user.lastName</saml:AttributeValue>
</saml:Attribute>
<saml:Attribute Name="role">
<saml:AttributeValue>user.role</saml:AttributeValue>
</saml:Attribute>
ステップ 2: ロールと権限を定義
// lib/permissions.ts
// システム内のすべての権限を定義
export const PERMISSIONS = {
// リソース: アクション
'users:read': 'ユーザーリストを表示',
'users:write': 'ユーザーを作成/更新',
'users:delete': 'ユーザーを削除',
'settings:read': '設定を表示',
'settings:write': '設定を変更',
'billing:read': '請求情報を表示',
'billing:write': '請求を管理',
'reports:read': 'レポートを表示',
'reports:export': 'レポートをエクスポート'
} as const
export type Permission = keyof typeof PERMISSIONS
// 権限を持つロールを定義
export const ROLES = {
'org:admin': [
'users:read', 'users:write', 'users:delete',
'settings:read', 'settings:write',
'billing:read', 'billing:write',
'reports:read', 'reports:export'
],
'org:manager': [
'users:read', 'users:write',
'settings:read',
'reports:read', 'reports:export'
],
'org:member': [
'users:read',
'reports:read'
],
'org:viewer': [
'reports:read'
]
} as const satisfies Record<string, Permission[]>
export type Role = keyof typeof ROLES
ステップ 3: 権限確認
// lib/auth-permissions.ts
import { auth } from '@clerk/nextjs/server'
import { ROLES, Permission, Role } from './permissions'
export async function hasPermission(permission: Permission): Promise<boolean> {
const { orgRole } = await auth()
if (!orgRole) return false
const role = orgRole as Role
const rolePermissions = ROLES[role]
if (!rolePermissions) return false
return rolePermissions.includes(permission)
}
export async function requirePermission(permission: Permission): Promise<void> {
const allowed = await hasPermission(permission)
if (!allowed) {
throw new Error(`Permission denied: ${permission}`)
}
}
// API ルートのデコレーターパターン
export function withPermission(permission: Permission) {
return async function(
handler: (req: Request) => Promise<Response>
): Promise<(req: Request) => Promise<Response>> {
return async (req: Request) => {
const allowed = await hasPermission(permission)
if (!allowed) {
return Response.json(
{ error: 'Permission denied', required: permission },
{ status: 403 }
)
}
return handler(req)
}
}
}
ステップ 4: RBAC による保護されたルート
// middleware.ts
import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server'
import { NextResponse } from 'next/server'
const isPublicRoute = createRouteMatcher(['/', '/sign-in(.*)', '/sign-up(.*)'])
const isAdminRoute = createRouteMatcher(['/admin(.*)'])
const isBillingRoute = createRouteMatcher(['/billing(.*)'])
export default clerkMiddleware(async (auth, request) => {
const { userId, orgRole } = await auth()
if (isPublicRoute(request)) {
return NextResponse.next()
}
if (!userId) {
return auth.redirectToSignIn()
}
// 管理者ルートは管理者ロールが必要
if (isAdminRoute(request)) {
if (orgRole !== 'org:admin') {
return NextResponse.redirect(new URL('/unauthorized', request.url))
}
}
// 請求ルートは管理者またはマネージャーが必要
if (isBillingRoute(request)) {
if (!['org:admin', 'org:manager'].includes(orgRole || '')) {
return NextResponse.redirect(new URL('/unauthorized', request.url))
}
}
return NextResponse.next()
})
ステップ 5: 組織管理
// lib/organization.ts
import { clerkClient, auth } from '@clerk/nextjs/server'
export async function createOrganization(name: string, slug: string) {
const { userId } = await auth()
const client = await clerkClient()
const org = await client.organizations.createOrganization({
name,
slug,
createdBy: userId!
})
return org
}
export async function inviteToOrganization(
orgId: string,
email: string,
role: string
) {
const client = await clerkClient()
const invitation = await client.organizations.createOrganizationInvitation({
organizationId: orgId,
emailAddress: email,
role,
inviterUserId: (await auth()).userId!
})
return invitation
}
export async function updateMemberRole(
orgId: string,
userId: string,
role: string
) {
const client = await clerkClient()
await client.organizations.updateOrganizationMembership({
organizationId: orgId,
userId,
role
})
}
export async function getOrganizationMembers(orgId: string) {
const client = await clerkClient()
const { data: members } = await client.organizations.getOrganizationMembershipList({
organizationId: orgId
})
return members
}
ステップ 6: RBAC を使用した React コンポーネント
// components/permission-gate.tsx
'use client'
import { useAuth, useOrganization } from '@clerk/nextjs'
import { ROLES, Permission, Role } from '@/lib/permissions'
interface PermissionGateProps {
permission: Permission
children: React.ReactNode
fallback?: React.ReactNode
}
export function PermissionGate({
permission,
children,
fallback = null
}: PermissionGateProps) {
const { orgRole } = useAuth()
if (!orgRole) return fallback
const role = orgRole as Role
const permissions = ROLES[role] || []
if (!permissions.includes(permission)) {
return fallback
}
return <>{children}</>
}
// 使用例
function AdminPanel() {
return (
<div>
<h1>Dashboard</h1>
<PermissionGate permission="users:write">
<button>Add User</button>
</PermissionGate>
<PermissionGate permission="billing:read">
<BillingSection />
</PermissionGate>
<PermissionGate
permission="settings:write"
fallback={<p>Contact admin for settings access</p>}
>
<SettingsForm />
</PermissionGate>
</div>
)
}
ステップ 7: API ルート保護
// app/api/admin/users/route.ts
import { auth } from '@clerk/nextjs/server'
import { hasPermission } from '@/lib/auth-permissions'
export async function GET() {
const { userId, orgId } = await auth()
if (!userId || !orgId) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
if (!await hasPermission('users:read')) {
return Response.json({ error: 'Forbidden' }, { status: 403 })
}
// 組織にスコープされたユーザーを取得
const users = await db.user.findMany({
where: { organizationId: orgId }
})
return Response.json(users)
}
export async function POST(request: Request) {
const { userId, orgId } = await auth()
if (!userId || !orgId) {
return Response.json({ error: 'Unauthorized' }, { status: 401 })
}
if (!await hasPermission('users:write')) {
return Response.json({ error: 'Forbidden' }, { status: 403 })
}
const data = await request.json()
const user = await db.user.create({
data: {
...data,
organizationId: orgId,
createdBy: userId
}
})
return Response.json(user)
}
SSO 設定マトリックス
| IdP | プロトコル | セットアップガイド |
|---|---|---|
| Okta | SAML 2.0 | Clerk Dashboard > SSO |
| Azure AD | OIDC/SAML | Clerk Dashboard > SSO |
| Google Workspace | OIDC | Clerk Dashboard > SSO |
| OneLogin | SAML 2.0 | Clerk Dashboard > SSO |
出力
- SAML SSO が設定される
- ロールと権限が定義される
- ミドルウェアで RBAC が実装される
- 組織管理が実装される
エラーハンドリング
| エラー | 原因 | 解決策 |
|---|---|---|
| SSO ログインに失敗 | IdP の設定ミス | 属性マッピングを確認 |
| 権限が拒否される | ロールが未設定 | ロール割り当てをレビュー |
| 組織が見つからない | ユーザーが組織に属していない | 組織選択を促す |
リソース
次のステップ
認証プロバイダーの移行については、clerk-migration-deep-dive に進みます。
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- Brmbobo
- リポジトリ
- Brmbobo/Web2podcast
- ライセンス
- MIT
- 最終更新
- 2026/1/26
Source: https://github.com/Brmbobo/Web2podcast / ライセンス: MIT
関連スキル
secure-code-guardian
認証・認可の実装、ユーザー入力の保護、OWASP Top 10の脆弱性対策が必要な場合に使用します。bcrypt/argon2によるパスワードハッシング、パラメータ化ステートメントによるSQLインジェクション対策、CORS/CSPヘッダーの設定、Zodによる入力検証、JWTトークンの構築などのカスタムセキュリティ実装に対応します。認証、認可、入力検証、暗号化、OWASP Top 10対策、セッション管理、セキュリティ強化全般で活用できます。ただし、構築済みのOAuth/SSO統合や単独のセキュリティ監査が必要な場合は、より特化したスキルの検討をお勧めします。
claude-authenticity
APIエンドポイントが本物のClaudeによって支えられているか(ラッパーやプロキシ、偽装ではないか)を、claude-verifyプロジェクトを模した9つの重み付きルールベースチェックで検証できます。また、Claudeの正体を上書きしているプロバイダーから注入されたシステムプロンプトも抽出します。完全に自己完結しており、httpx以外の追加パッケージは不要です。Claude APIキーまたはエンドポイントを検証したい場合、サードパーティのClaudeサービスが本物か確認したい場合、APIプロバイダーのClaude正当性を監査したい場合、複数モデルを並行してテストしたい場合、またはプロバイダーが注入したシステムプロンプトを特定したい場合に使用できます。
anth-security-basics
Anthropic Claude APIのセキュリティベストプラクティスを適用し、キー管理、入力値の検証、プロンプトインジェクション対策を実施します。APIキーの保護、Claudeに送信する前のユーザー入力検証、コンテンツセーフティガードレールの実装が必要な場合に活用できます。「anthropic security」「claude api key security」「secure anthropic」「prompt injection defense」といったフレーズでトリガーされます。
x-ray
x-ray.mdプレ監査レポートを生成します。概要、強化された脅威モデル(プロトコルタイプのプロファイリング、Gitの重み付け攻撃面分析、時間軸リスク分析、コンポーザビリティ依存関係マッピング)、不変条件、統合、ドキュメント品質、テスト分析、開発者・Gitの履歴をカバーしています。「x-ray」「audit readiness」「readiness report」「pre-audit report」「prep this protocol」「protocol prep」「summarize this protocol」のキーワードで実行されます。
semgrep
Semgrepスタティック分析スキャンを実行し、カスタム検出ルールを作成します。Semgrepでのコードスキャン、セキュリティ脆弱性の検出、カスタムYAMLルールの作成、または特定のバグパターンの検出が必要な場合に使用します。重要:ユーザーが「バグをスキャンしたい」「コード品質を確認したい」「脆弱性を見つけたい」「スタティック分析」「セキュリティlint」「コード監査」または「コーディング標準を適用したい」と尋ねた場合も、Semgrepという名称を明記していなくても、このスキルを使用してください。Semgrepは30以上の言語に対応したパターンベースのコードスキャンに最適なツールです。
ghost-bits-cast-attack
Java「ゴーストビッツ」/キャストアタック プレイブック(Black Hat Asia 2026)。16ビット文字が8ビットバイトに暗黙的に縮小されるJavaサービスへの攻撃時に使用します。WAF/IDSを回避して、SQLインジェクション、デシリアライゼーション型RCE、ファイルアップロード(Webシェル)、パストトラバーサル、CRLF インジェクション、リクエストスマグリング、SMTPインジェクションを実行できます。Tomcat、Spring、Jetty、Undertow、Vert.x、Jackson、Fastjson、Apache Commons BCEL、Apache HttpClient、Angus Mail、JDK HttpServer、Lettuce、Jodd、XMLWriterに影響し、WAFバイパスにより多くの「パッチ済み」CVEを再度有効化します。