npx skills add https://github.com/clerk/skills --skill clerk-orgs前提条件:首先在 Clerk Dashboard 中启用组织功能。
版本:请查看
package.json中的 SDK 版本——版本表请参见clerk技能。Core 2 的差异在文中以> **仅限 Core 2(当前 SDK 请跳过):**标注说明。
| 任务 | 链接 |
|---|---|
| 概述 | https://clerk.com/docs/guides/organizations/overview |
| URL 中的组织标识符 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
| 角色与权限 | https://clerk.com/docs/guides/organizations/control-access/roles-and-permissions |
| 检查访问权限 | https://clerk.com/docs/guides/organizations/control-access/check-access |
| 邀请 | https://clerk.com/docs/guides/organizations/add-members/invitations |
| OrganizationSwitcher | https://clerk.com/docs/reference/components/organization/organization-switcher |
| 已验证域名 | https://clerk.com/docs/guides/organizations/verified-domains |
| 企业单点登录 | https://clerk.com/docs/guides/organizations/add-members/sso |
服务器端访问组织:
import { auth } from '@clerk/nextjs/server'
const { orgId, orgSlug } = await auth()
console.log(`Current org: ${orgSlug}`)
创建接受组织标识符的路由:
app/orgs/[slug]/page.tsx
app/orgs/[slug]/settings/page.tsx
访问标识符:
export default function DashboardPage({ params }: { params: { slug: string } }) {
return <div>Organization: {params.slug}</div>
}
验证用户是否有权访问特定组织:
import { auth } from '@clerk/nextjs/server'
export default async function ProtectedPage() {
const { orgId, orgSlug } = await auth()
if (!orgId) {
return <div>Not in an organization</div>
}
return <div>Welcome to {orgSlug}</div>
}
检查用户是否具有特定角色:
const { has } = await auth()
if (!has({ role: 'org:admin' })) {
return <div>Admin access required</div>
}
让用户在组织之间切换:
import { OrganizationSwitcher } from '@clerk/nextjs'
export default function Nav() {
return (
<header>
<h1>Dashboard</h1>
<OrganizationSwitcher />
</header>
)
}
所有新成员都会被分配一个角色:
| 角色 | 权限 |
|---|---|
org:admin | 完全访问权限,管理成员、设置 |
org:member | 受限访问权限,只读 |
可以在仪表板中创建自定义角色。
| 权限 | 角色 |
|---|---|
org:create | 可以创建新组织 |
org:manage_members | 可以邀请/移除成员(默认:管理员) |
org:manage_roles | 可以更改成员角色(默认:管理员) |
org:update_metadata | 可以更新组织元数据(默认:管理员) |
保护路由的完整示例:
import { auth } from '@clerk/nextjs/server'
import { redirect } from 'next/navigation'
export default async function AdminPage({ params }: { params: { slug: string } }) {
const { orgSlug, has } = await auth()
// 验证用户是否在该组织中
if (orgSlug !== params.slug) {
redirect('/dashboard')
}
// 检查是否为管理员
if (!has({ role: 'org:admin' })) {
redirect(`/orgs/${orgSlug}`)
}
return <div>Admin settings for {orgSlug}</div>
}
<Show> 进行条件渲染在客户端组件中使用 <Show> 进行基于角色的条件渲染:
import { Show } from '@clerk/nextjs'
<Show when={{ role: 'org:admin' }}>
<AdminPanel />
</Show>
<Show when={{ permission: 'org:billing:manage' }}>
<BillingSettings />
</Show>
仅限 Core 2(当前 SDK 请跳过): 请使用
<Protect role="org:admin">和<Protect permission="org:billing:manage">代替<Show>。
has() 方法支持计费计划和功能检查,用于控制访问权限:
const { has } = await auth()
has({ plan: 'gold' }) // 检查订阅计划
has({ feature: 'widgets' }) // 检查功能授权
仅限 Core 2(当前 SDK 请跳过):
has()仅支持role和permission参数。计费检查不可用。
当个人账户被禁用时,用户登录后必须选择一个组织。这由 choose-organization 会话任务处理:
import { TaskChooseOrganization } from '@clerk/nextjs'
// 当用户必须选择组织时渲染
<TaskChooseOrganization redirectUrlComplete="/dashboard" />
仅限 Core 2(当前 SDK 请跳过): 会话任务不可用。请使用
<OrganizationSwitcher>进行组织选择。
组织可以使用企业单点登录(SAML/OIDC)进行成员认证:
// 企业单点登录的策略名称
strategy: 'enterprise_sso'
// 访问用户对象上的企业账户
user.enterpriseAccounts
仅限 Core 2(当前 SDK 请跳过): 使用
strategy: 'saml'代替strategy: 'enterprise_sso',使用user.samlAccounts代替user.enterpriseAccounts。
| 症状 | 原因 | 解决方案 |
|---|---|---|
orgSlug 未定义 | 未调用 await auth() | 使用 const { orgSlug } = await auth() |
| 角色检查总是失败 | 未等待 auth() | 在 auth() 前添加 await |
| 用户可以访问其他组织 | 未检查 orgSlug 是否与 URL 匹配 | 验证 orgSlug === params.slug |
| 组织未出现在切换器中 | 未启用组织功能 | 在 Clerk Dashboard → Organizations 中启用 |
| 邀请不起作用 | 角色配置错误 | 确保成员拥有邀请角色的权限 |
每周安装量
1.5K
代码仓库
GitHub 星标数
22
首次出现
2026年1月30日
安全审计
安装于
codex1.3K
opencode1.3K
gemini-cli1.3K
github-copilot1.3K
amp1.2K
kimi-cli1.2K
Prerequisite : Enable Organizations in Clerk Dashboard first.
Version : Check
package.jsonfor the SDK version — seeclerkskill for the version table. Core 2 differences are noted inline with> **Core 2 ONLY (skip if current SDK):**callouts.
Server-side access to organization:
import { auth } from '@clerk/nextjs/server'
const { orgId, orgSlug } = await auth()
console.log(`Current org: ${orgSlug}`)
Create routes that accept org slug:
app/orgs/[slug]/page.tsx
app/orgs/[slug]/settings/page.tsx
Access the slug:
export default function DashboardPage({ params }: { params: { slug: string } }) {
return <div>Organization: {params.slug}</div>
}
Verify user has access to specific org:
import { auth } from '@clerk/nextjs/server'
export default async function ProtectedPage() {
const { orgId, orgSlug } = await auth()
if (!orgId) {
return <div>Not in an organization</div>
}
return <div>Welcome to {orgSlug}</div>
}
Check if user has specific role:
const { has } = await auth()
if (!has({ role: 'org:admin' })) {
return <div>Admin access required</div>
}
Let users switch between organizations:
import { OrganizationSwitcher } from '@clerk/nextjs'
export default function Nav() {
return (
<header>
<h1>Dashboard</h1>
<OrganizationSwitcher />
</header>
)
}
All new members get assigned a role:
| Role | Permissions |
|---|---|
org:admin | Full access, manage members, settings |
org:member | Limited access, read-only |
Custom roles can be created in the dashboard.
| Permission | Role |
|---|---|
org:create | Can create new organizations |
org:manage_members | Can invite/remove members (default: admin) |
org:manage_roles | Can change member roles (default: admin) |
org:update_metadata | Can update org metadata (default: admin) |
Complete example protecting a route:
import { auth } from '@clerk/nextjs/server'
import { redirect } from 'next/navigation'
export default async function AdminPage({ params }: { params: { slug: string } }) {
const { orgSlug, has } = await auth()
// Verify user is in the org
if (orgSlug !== params.slug) {
redirect('/dashboard')
}
// Check if admin
if (!has({ role: 'org:admin' })) {
redirect(`/orgs/${orgSlug}`)
}
return <div>Admin settings for {orgSlug}</div>
}
<Show>Use <Show> for role-based conditional rendering in client components:
import { Show } from '@clerk/nextjs'
<Show when={{ role: 'org:admin' }}>
<AdminPanel />
</Show>
<Show when={{ permission: 'org:billing:manage' }}>
<BillingSettings />
</Show>
Core 2 ONLY (skip if current SDK): Use
<Protect role="org:admin">and<Protect permission="org:billing:manage">instead of<Show>.
The has() method supports billing plan and feature checks for gating access:
const { has } = await auth()
has({ plan: 'gold' }) // Check subscription plan
has({ feature: 'widgets' }) // Check feature entitlement
Core 2 ONLY (skip if current SDK):
has()only supportsroleandpermissionparameters. Billing checks are not available.
When personal accounts are disabled, users must choose an organization after sign-in. This is handled by the choose-organization session task:
import { TaskChooseOrganization } from '@clerk/nextjs'
// Renders when user must select an org
<TaskChooseOrganization redirectUrlComplete="/dashboard" />
Core 2 ONLY (skip if current SDK): Session tasks are not available. Use
<OrganizationSwitcher>for org selection.
Organizations can use Enterprise SSO (SAML/OIDC) for member authentication:
// Strategy name for Enterprise SSO
strategy: 'enterprise_sso'
// Access enterprise accounts on user object
user.enterpriseAccounts
Core 2 ONLY (skip if current SDK): Uses
strategy: 'saml'instead ofstrategy: 'enterprise_sso', anduser.samlAccountsinstead ofuser.enterpriseAccounts.
| Symptom | Cause | Solution |
|---|---|---|
orgSlug is undefined | Not calling await auth() | Use const { orgSlug } = await auth() |
| Role check always fails | Not awaiting auth() | Add await before auth() |
| Users can access other orgs | Not checking orgSlug matches URL | Verify orgSlug === params.slug |
Weekly Installs
1.5K
Repository
GitHub Stars
22
First Seen
Jan 30, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
codex1.3K
opencode1.3K
gemini-cli1.3K
github-copilot1.3K
amp1.2K
kimi-cli1.2K
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
102,200 周安装
| Org not appearing in switcher | Organizations not enabled | Enable in Clerk Dashboard → Organizations |
| Invitations not working | Wrong role configuration | Ensure members have invite role permissions |