diff --git a/docs/_partials/has-warning.mdx b/docs/_partials/has-warning.mdx index 3e719d42ce..b55b330eee 100644 --- a/docs/_partials/has-warning.mdx +++ b/docs/_partials/has-warning.mdx @@ -1,2 +1,2 @@ > [!WARNING] -> Using `has()` **on the server-side** to check Permissions works only with **Custom Permissions**, as [System Permissions](/docs/guides/organizations/roles-and-permissions#system-permissions) aren't included in the session token claims. To check System Permissions, verify the user's Role instead. +> Using `has()` **on the server-side** to check Permissions works only with **Custom Permissions**, as [System Permissions](/docs/guides/organizations/control-access/roles-and-permissions#system-permissions) aren't included in the session token claims. To check System Permissions, verify the user's Role instead. diff --git a/docs/_partials/organization-get-started-next-steps.mdx b/docs/_partials/organization-get-started-next-steps.mdx new file mode 100644 index 0000000000..7c830f84e5 --- /dev/null +++ b/docs/_partials/organization-get-started-next-steps.mdx @@ -0,0 +1,11 @@ +You've added Clerk Organizations to your app 🎉. + +To make configuration changes to your Clerk development instance, claim the Clerk keys that were generated for you by selecting **Claim your application** in the bottom right of your app. This will associate the application with your Clerk account. + +Here are some next steps you can take to scale your app: + +- **Control access** with [Custom Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions): define granular Permissions for different user types within Organizations. + +- **Onboard entire companies** with [Verified Domains](/docs/guides/organizations/add-members/verified-domains): automatically invite users with approved email domains (e.g. `@company.com`) to join Organizations without manual invitations. + +- **Enable Enterprise SSO** with [SAML and OIDC](/docs/guides/organizations/add-members/sso): let customers authenticate through their identity provider (e.g. Okta, Entra ID, Google Workspace) with unlimited connections, no per-connection fees. diff --git a/docs/_partials/organization-sync-options.mdx b/docs/_partials/organization-sync-options.mdx index 24fd15d8a7..8f3e5cfa1b 100644 --- a/docs/_partials/organization-sync-options.mdx +++ b/docs/_partials/organization-sync-options.mdx @@ -25,7 +25,7 @@ object has the type `OrganizationSyncOptions`, which has the following propertie - `personalAccountPatterns` - [Pattern](#pattern)\[] - URL patterns for resources that exist within the context of a user's [Personal Account](/docs/guides/organizations/overview#allow-personal-accounts). + URL patterns for resources that exist within the context of a user's [Personal Account](/docs/guides/organizations/configure#allow-personal-accounts). If the route also matches the `organizationPattern` prop, the `organizationPattern` prop takes precedence. diff --git a/docs/_tooltips/choose-organization.mdx b/docs/_tooltips/choose-organization.mdx new file mode 100644 index 0000000000..521bd31769 --- /dev/null +++ b/docs/_tooltips/choose-organization.mdx @@ -0,0 +1 @@ +This happens because the `choose-organization` session task must be completed before the user's authentication process can be considered complete. Session tasks are pending requirements that users must complete after authentication. Learn more about [session tasks](/docs/guides/configure/session-tasks). diff --git a/docs/getting-started/quickstart.astro.mdx b/docs/getting-started/quickstart.astro.mdx index 49d4daacda..171d08cd2e 100644 --- a/docs/getting-started/quickstart.astro.mdx +++ b/docs/getting-started/quickstart.astro.mdx @@ -11,11 +11,6 @@ sdk: astro link: "/docs/getting-started/quickstart/setup-clerk", icon: "clerk", }, - { - title: "Create an Astro application", - link: "https://docs.astro.build/en/install-and-setup", - icon: "astro", - }, ]} exampleRepo={[ { @@ -26,6 +21,17 @@ sdk: astro /> + ## Create an Astro app + + Run the following commands to create a new Astro app. + + ```npm + npm create astro@latest clerk-astro --template react-ts + cd clerk-astro + npm install + npm run dev + ``` + ## Install `@clerk/astro` The [Clerk Astro SDK](/docs/reference/astro/overview) provides a set of components, hooks, and stores that make it easy to build authentication and user management features in your Astro app. @@ -141,10 +147,16 @@ sdk: astro ```astro {{ filename: 'src/pages/index.astro' }} --- import Layout from '../layouts/Layout.astro' + import { SignedIn, SignedOut } from '@clerk/astro/components' --- -

Sign in to try Clerk out!

+ +

Sign in to try Clerk out!

+
+ +

You are signed in!

+
``` diff --git a/docs/getting-started/quickstart.expo.mdx b/docs/getting-started/quickstart.expo.mdx index 503a463309..d6e2583122 100644 --- a/docs/getting-started/quickstart.expo.mdx +++ b/docs/getting-started/quickstart.expo.mdx @@ -6,23 +6,18 @@ sdk: expo @@ -30,6 +25,17 @@ sdk: expo + ## Create an Expo app + + Run the following commands to create a new Expo app. + + ```npm + npx create-expo-app@latest clerk-expo --template react-ts + cd clerk-expo + npm install + npm run dev + ``` + ## Install `@clerk/clerk-expo` The [Clerk Expo SDK](/docs/reference/expo/overview) gives you access to prebuilt components, hooks, and helpers to make user authentication easier. diff --git a/docs/getting-started/quickstart.ios.mdx b/docs/getting-started/quickstart.ios.mdx index 7cf67afc76..5ad9f9dcdb 100644 --- a/docs/getting-started/quickstart.ios.mdx +++ b/docs/getting-started/quickstart.ios.mdx @@ -6,12 +6,12 @@ sdk: ios diff --git a/docs/getting-started/quickstart.nuxt.mdx b/docs/getting-started/quickstart.nuxt.mdx index a6655a9be8..6b330be840 100644 --- a/docs/getting-started/quickstart.nuxt.mdx +++ b/docs/getting-started/quickstart.nuxt.mdx @@ -17,15 +17,21 @@ sdk: nuxt link: "/docs/getting-started/quickstart/setup-clerk", icon: "clerk", }, - { - title: "Create a Nuxt application", - link: "https://nuxt.com/docs/getting-started/installation", - icon: "nuxt" - } ]} /> + ## Create a Nuxt App + + Run the following commands to create a new Nuxt app. + + ```npm + npm create nuxt@latest clerk-nuxt --template react-ts + cd clerk-nuxt + npm install + npm run dev + ``` + ## Install `@clerk/nuxt` The [Clerk Nuxt SDK](/docs/reference/nuxt/overview) gives you access to prebuilt components, Vue composables, and helpers to make user authentication easier. diff --git a/docs/getting-started/quickstart.react-router.mdx b/docs/getting-started/quickstart.react-router.mdx index 6780e1f68c..41d0f0f5ee 100644 --- a/docs/getting-started/quickstart.react-router.mdx +++ b/docs/getting-started/quickstart.react-router.mdx @@ -17,11 +17,6 @@ sdk: react-router title: "Set up a Clerk application", link: "/docs/getting-started/quickstart/setup-clerk", icon: "clerk", - }, - { - title: "Create a React Router application", - link: "https://reactrouter.com/start/framework/installation", - icon: "react-router", } ]} /> @@ -31,6 +26,17 @@ React Router can be used in different modes: **declarative**, **data**, or **fra This tutorial assumes that you're using React Router **v7.1.2 or later** in framework mode. + ## Create a React app using React Router + + Run the following commands to create a new React app using React Router. + + ```npm + npm create react-router clerk-react-router --template react-ts + cd clerk-react-router + npm install + npm run dev + ``` + ## Install `@clerk/react-router` The [Clerk React Router SDK](/docs/reference/react-router/overview) provides prebuilt components, hooks, and helpers to make it easy to integrate authentication and user management in your React Router app. @@ -67,14 +73,14 @@ This tutorial assumes that you're using React Router **v7.1.2 or later** in fram React Router middleware requires opting in via a future flag. Add the following to your `react-router.config.ts` file: ```ts {{ filename: 'react-router.config.ts' }} - import type { Config } from '@react-router/dev/config' - - export default { - // ... - future: { - v8_middleware: true, - }, - } satisfies Config + import type { Config } from '@react-router/dev/config' + + export default { + // ... + + future: { + + v8_middleware: true, + + }, + } satisfies Config ``` Then, add the following code to your `root.tsx` file to configure the `clerkMiddleware()` and `rootAuthLoader()` functions. @@ -168,7 +174,7 @@ This tutorial assumes that you're using React Router **v7.1.2 or later** in fram - [``](/docs/reference/components/user/user-button): Shows the signed-in user's avatar. Selecting it opens a dropdown menu with account management options. - [``](/docs/reference/components/unstyled/sign-in-button): An unstyled component that links to the sign-in page. In this example, since no props or [environment variables](/docs/guides/development/clerk-environment-variables) are set for the sign-in URL, this component links to the [Account Portal sign-in page](/docs/guides/customizing-clerk/account-portal#sign-in). - ```tsx {{ filename: 'app/root.tsx', mark: [44, [46, 58], 60], fold: [[2, 42], [62, 87]] }} + ```tsx {{ filename: 'app/root.tsx', mark: [1, 44, [46, 60]], fold: [[2, 42], [62, 87]] }} import { ClerkProvider, SignedIn, SignedOut, UserButton, SignInButton } from '@clerk/react-router' import { isRouteErrorResponse, Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router' import { clerkMiddleware, rootAuthLoader } from '@clerk/react-router/server' diff --git a/docs/getting-started/quickstart.react.mdx b/docs/getting-started/quickstart.react.mdx index 133b043d4b..e6b032ea40 100644 --- a/docs/getting-started/quickstart.react.mdx +++ b/docs/getting-started/quickstart.react.mdx @@ -110,21 +110,26 @@ This tutorial will demonstrate how to create a new React app using Vite and add - [``](/docs/reference/components/user/user-button): Shows the signed-in user's avatar. Selecting it opens a dropdown menu with account management options. - [``](/docs/reference/components/unstyled/sign-in-button): An unstyled component that links to the sign-in page. In this example, since no props or [environment variables](/docs/guides/development/clerk-environment-variables) are set for the sign-in URL, this component links to the [Account Portal sign-in page](/docs/guides/customizing-clerk/account-portal#sign-in). - ```tsx {{ filename: 'src/App.tsx', mark: [1, [5, 12]] }} + ```tsx {{ filename: 'src/App.tsx', mark: [2, [7, 14]] }} + import './App.css' import { SignedIn, SignedOut, SignInButton, UserButton } from '@clerk/clerk-react' - export default function App() { + function App() { return ( -
- - - - - - -
+ <> +
+ + + + + + +
+ ) } + + export default App ``` ## Create your first user diff --git a/docs/guides/billing/for-b2b.mdx b/docs/guides/billing/for-b2b.mdx index 194eb72cf0..aa9532afd0 100644 --- a/docs/guides/billing/for-b2b.mdx +++ b/docs/guides/billing/for-b2b.mdx @@ -12,7 +12,7 @@ Clerk Billing for B2B SaaS allows you to create Plans and manage Subscriptions * ## Create a Plan -Subscription Plans are what your customers subscribe to. There is no limit to the number of Plans you can create. If your Clerk instance has existing [Custom Permissions](/docs/guides/organizations/roles-and-permissions), the corresponding Features from those Permissions will automatically be added to the free Plan for Orgs. This ensures that Organization members get the same set of Custom Permissions when Billing is enabled, because all Organizations start on the free Plan. +Subscription Plans are what your customers subscribe to. There is no limit to the number of Plans you can create. If your Clerk instance has existing [Custom Permissions](/docs/guides/organizations/control-access/roles-and-permissions), the corresponding Features from those Permissions will automatically be added to the Free Plan for Organizations. This ensures that Organization members get the same set of Custom Permissions when Billing is enabled, because all Organizations start on the Free Plan. To create a Plan, navigate to the [**Subscription plans**](https://dashboard.clerk.com/~/billing/plans) page in the Clerk Dashboard. Here, you can create, edit, and delete Plans. To setup B2B Billing, select the **Plans for Organizations** tab and select **Add Plan**. When creating a Plan, you can also create [Features](/docs/guides/secure/features) for the Plan; see the next section for more information. diff --git a/docs/guides/configure/auth-strategies/social-connections/dropbox.mdx b/docs/guides/configure/auth-strategies/social-connections/dropbox.mdx index 1b52aec691..686c91e132 100644 --- a/docs/guides/configure/auth-strategies/social-connections/dropbox.mdx +++ b/docs/guides/configure/auth-strategies/social-connections/dropbox.mdx @@ -5,17 +5,17 @@ description: Learn how to allow users to sign up and sign in to your Clerk app w Enabling OAuth with Dropbox allows your users to sign up and sign in to your Clerk application with their Dropbox account. diff --git a/docs/guides/configure/auth-strategies/social-connections/facebook.mdx b/docs/guides/configure/auth-strategies/social-connections/facebook.mdx index 6969fb62ba..adba78569d 100644 --- a/docs/guides/configure/auth-strategies/social-connections/facebook.mdx +++ b/docs/guides/configure/auth-strategies/social-connections/facebook.mdx @@ -5,17 +5,17 @@ description: Learn how to allow users to sign up and sign in to your Clerk app w Enabling OAuth with Facebook allows your users to sign up and sign in to your Clerk app with their Facebook account. diff --git a/docs/guides/configure/auth-strategies/social-connections/twitch.mdx b/docs/guides/configure/auth-strategies/social-connections/twitch.mdx index 11cc33b702..9671264132 100644 --- a/docs/guides/configure/auth-strategies/social-connections/twitch.mdx +++ b/docs/guides/configure/auth-strategies/social-connections/twitch.mdx @@ -5,17 +5,17 @@ description: Learn how to allow users to sign up and sign in to your Clerk app w Enabling OAuth with [Twitch](https://dev.twitch.tv/docs/api/reference#oauth-client-credentials-flow) allows your users to sign up and sign in to your Clerk application with their Twitch account. diff --git a/docs/guides/configure/session-tasks.mdx b/docs/guides/configure/session-tasks.mdx index eb540eda59..5e4ca70ec7 100644 --- a/docs/guides/configure/session-tasks.mdx +++ b/docs/guides/configure/session-tasks.mdx @@ -33,7 +33,7 @@ The following table lists the available tasks and their corresponding components | Name | Component | | - | - | -| [Personal accounts disabled (default)](/docs/guides/organizations/overview#allow-personal-accounts) | [``](/docs/reference/components/authentication/task-choose-organization) | +| [Personal accounts disabled (default)](/docs/guides/organizations/configure#enable-organizations) | [``](/docs/reference/components/authentication/task-choose-organization) | > [!IMPORTANT] > Personal accounts being disabled by default was released on 08-22-2025. Applications created before this date will not be able to see the **Allow Personal Accounts** setting, because Personal Accounts were enabled by default. @@ -272,7 +272,7 @@ The `useAuth()` hook and helpers that access the [`Auth` object](/docs/reference #### Example: Personal accounts disabled -When Organizations are enabled, [Personal Accounts are disabled by default](/docs/guides/organizations/overview#allow-personal-accounts) and your users will be required to select or create an Organization after authenticating. Until completed, their session remains `pending`. Pages that are protected using Clerk's protection utilities will treat the user's session as signed-out. +When Organizations are enabled, [Personal Accounts are disabled by default](/docs/guides/organizations/configure#allow-personal-accounts) and your users will be required to select or create an Organization after authenticating. Until completed, their session remains `pending`. Pages that are protected using Clerk's protection utilities will treat the user's session as signed-out. For `useAuth()`, `isSignedIn` will be `false` and `userId` and `orgId` will be `null` if the user has a `pending` session. diff --git a/docs/guides/development/custom-flows/account-updates/user-impersonation.mdx b/docs/guides/development/custom-flows/account-updates/user-impersonation.mdx index 41a4681760..c13df22db6 100644 --- a/docs/guides/development/custom-flows/account-updates/user-impersonation.mdx +++ b/docs/guides/development/custom-flows/account-updates/user-impersonation.mdx @@ -13,7 +13,7 @@ This guide will walk you through how to build a custom flow that handles user im - The following example builds a dashboard that is only accessible to users with the `org:admin:impersonate` permission. To use this example, you must first [create the custom `org:admin:impersonate` permission](/docs/guides/organizations/roles-and-permissions#custom-permissions). Or you can modify the [authorization checks](!authorization-check) to fit your use case. + The following example builds a dashboard that is only accessible to users with the `org:admin:impersonate` permission. To use this example, you must first [create the custom `org:admin:impersonate` permission](/docs/guides/organizations/control-access/roles-and-permissions#custom-permissions). Or you can modify the [authorization checks](!authorization-check) to fit your use case. In the dashboard, the user will see a list of the application's users. When the user chooses to impersonate a user, they will be signed in as that user and redirected to the homepage. diff --git a/docs/guides/development/custom-flows/organizations/accept-organization-invitations.mdx b/docs/guides/development/custom-flows/organizations/accept-organization-invitations.mdx index e7571284ff..34e820ccf3 100644 --- a/docs/guides/development/custom-flows/organizations/accept-organization-invitations.mdx +++ b/docs/guides/development/custom-flows/organizations/accept-organization-invitations.mdx @@ -5,11 +5,11 @@ description: Learn how to use the Clerk API to build a custom flows for acceptin -When a user visits an [Organization invitation](/docs/guides/organizations/invitations) link, Clerk first checks whether a custom redirect URL was provided. +When a user visits an [Organization invitation](/docs/guides/organizations/add-members/invitations) link, Clerk first checks whether a custom redirect URL was provided. **If no redirect URL is specified**, the user will be redirected to the appropriate Account Portal page (either [sign-up](/docs/guides/customizing-clerk/account-portal#sign-up) or [sign-in](/docs/guides/customizing-clerk/account-portal#sign-in)), or to the custom sign-up/sign-in pages that you've configured for your application. -**If you specified [a redirect URL when creating the invitation](/docs/guides/organizations/invitations#redirect-url)**, you must handle the authentication flows in your code for that page. You can either embed the [``](/docs/reference/components/authentication/sign-in) component on that page, or if the prebuilt component doesn't meet your specific needs or if you require more control over the logic, you can rebuild the existing Clerk flows using the Clerk API. +**If you specified [a redirect URL when creating the invitation](/docs/guides/organizations/add-members/invitations#redirect-url)**, you must handle the authentication flows in your code for that page. You can either embed the [``](/docs/reference/components/authentication/sign-in) component on that page, or if the prebuilt component doesn't meet your specific needs or if you require more control over the logic, you can rebuild the existing Clerk flows using the Clerk API. This guide demonstrates how to use Clerk's API to build a custom flow for accepting Organization invitations from a link. diff --git a/docs/guides/development/custom-flows/organizations/manage-membership-requests.mdx b/docs/guides/development/custom-flows/organizations/manage-membership-requests.mdx index 21fbe78110..487849a050 100644 --- a/docs/guides/development/custom-flows/organizations/manage-membership-requests.mdx +++ b/docs/guides/development/custom-flows/organizations/manage-membership-requests.mdx @@ -5,7 +5,7 @@ description: Learn how to use the Clerk API to build a custom flow for managing -This guide will demonstrate how to use the Clerk API to build a custom flow for managing [Organization membership requests](/docs/guides/organizations/verified-domains#membership-requests). +This guide will demonstrate how to use the Clerk API to build a custom flow for managing [Organization membership requests](/docs/guides/organizations/add-members/verified-domains#membership-requests). diff --git a/docs/guides/development/custom-flows/organizations/manage-organization-invitations.mdx b/docs/guides/development/custom-flows/organizations/manage-organization-invitations.mdx index a25d9c11c8..b22ef42059 100644 --- a/docs/guides/development/custom-flows/organizations/manage-organization-invitations.mdx +++ b/docs/guides/development/custom-flows/organizations/manage-organization-invitations.mdx @@ -5,14 +5,14 @@ description: Learn how to use the Clerk API to build a custom flow for creating -Organization members with appropriate [Permissions](/docs/guides/organizations/roles-and-permissions) can invite new users to their Organization and manage those invitations. The invitation recipient can be either an existing user of your application or a new user. If they are a new user, they will need to sign up in order to accept the invitation. +Organization members with appropriate [Permissions](/docs/guides/organizations/control-access/roles-and-permissions) can invite new users to their Organization and manage those invitations. The invitation recipient can be either an existing user of your application or a new user. If they are a new user, they will need to sign up in order to accept the invitation. Users with the appropriate Permissions can also revoke Organization invitations for users that have not yet joined, which will prevent the user from becoming an Organization member. This guide will demonstrate how to use the Clerk API to build a custom flow for inviting users to an Organization and managing an Organization's pending invitations. > [!NOTE] -> This guide is for creating and managing Organization invitations client-side. You can also create an Organization invitation using the Backend API. See the [Organization invitations reference](/docs/guides/organizations/invitations) for more information. +> This guide is for creating and managing Organization invitations client-side. You can also create an Organization invitation using the Backend API. See the [Organization invitations reference](/docs/guides/organizations/add-members/invitations) for more information. > > Also, see the [custom flow for accepting Organization invitations](/docs/guides/development/custom-flows/organizations/accept-organization-invitations). diff --git a/docs/guides/development/custom-flows/organizations/manage-roles.mdx b/docs/guides/development/custom-flows/organizations/manage-roles.mdx index 1e9880ccd6..6221407dc7 100644 --- a/docs/guides/development/custom-flows/organizations/manage-roles.mdx +++ b/docs/guides/development/custom-flows/organizations/manage-roles.mdx @@ -5,7 +5,7 @@ description: Learn how to use the Clerk API build a custom flow for managing mem -Organization members with appropriate [Permissions](/docs/guides/organizations/roles-and-permissions#permissions) can manage a member's [Roles](/docs/guides/organizations/roles-and-permissions#roles) and remove members within an Organization. +Organization members with appropriate [Permissions](/docs/guides/organizations/control-access/roles-and-permissions#permissions) can manage a member's [Roles](/docs/guides/organizations/control-access/roles-and-permissions#roles) and remove members within an Organization. This guide will demonstrate how to use the Clerk API to build a custom flow for managing member Roles in an Organization. diff --git a/docs/guides/development/custom-flows/organizations/manage-user-org-invitations.mdx b/docs/guides/development/custom-flows/organizations/manage-user-org-invitations.mdx index af88b52faa..756d8096d9 100644 --- a/docs/guides/development/custom-flows/organizations/manage-user-org-invitations.mdx +++ b/docs/guides/development/custom-flows/organizations/manage-user-org-invitations.mdx @@ -5,7 +5,7 @@ description: Learn how to use the Clerk API to build a custom flow for managing -This guide will demonstrate how to use the Clerk API to build a custom flow for managing a user's [Organization invitations](/docs/guides/organizations/overview#organization-invitations). +This guide will demonstrate how to use the Clerk API to build a custom flow for managing a user's [Organization invitations](/docs/guides/organizations/add-members/invitations). diff --git a/docs/guides/development/custom-flows/organizations/update-organizations.mdx b/docs/guides/development/custom-flows/organizations/update-organizations.mdx index e9438a956f..3c3ee5bb0f 100644 --- a/docs/guides/development/custom-flows/organizations/update-organizations.mdx +++ b/docs/guides/development/custom-flows/organizations/update-organizations.mdx @@ -5,7 +5,7 @@ description: Learn how to use the Clerk API to build a custom flow for updating -Organization members with appropriate [Permissions](/docs/guides/organizations/roles-and-permissions) can update an Organization. +Organization members with appropriate [Permissions](/docs/guides/organizations/control-access/roles-and-permissions) can update an Organization. This guide will demonstrate how to use Clerk's API to build a custom flow for updating an Organization. diff --git a/docs/guides/development/integrations/platforms/shopify.mdx b/docs/guides/development/integrations/platforms/shopify.mdx index 307d42ee54..8c2f5b0f65 100644 --- a/docs/guides/development/integrations/platforms/shopify.mdx +++ b/docs/guides/development/integrations/platforms/shopify.mdx @@ -5,17 +5,17 @@ description: Learn how to integrate Clerk into your Shopify store. This tutorial outlines how to integrate Clerk's authentication with your Shopify Plus store, allowing you to use Clerk as your identity provider for customer logins. In Shopify, using [your own Identity Provider for customer login](https://changelog.shopify.com/posts/use-your-own-identity-provider-for-customer-login) is only available to stores on the **Shopify Plus plan**. diff --git a/docs/guides/development/mcp/build-mcp-server.mdx b/docs/guides/development/mcp/build-mcp-server.mdx index 5184563745..e095a30dbd 100644 --- a/docs/guides/development/mcp/build-mcp-server.mdx +++ b/docs/guides/development/mcp/build-mcp-server.mdx @@ -7,23 +7,23 @@ sdk: nextjs, expressjs This guide demonstrates how to build an MCP server using Clerk's OAuth server in your Next.js app. This example is written for Next.js App Router, but **can be adapted for Next.js Pages Router**. It assumes that you have already integrated Clerk into your app by following the [quickstart](/docs/nextjs/getting-started/quickstart). @@ -32,23 +32,23 @@ sdk: nextjs, expressjs This guide demonstrates how to build an MCP server using Clerk's OAuth server in your Express app. It assumes that you have already integrated Clerk into your app by following the [quickstart](/docs/nextjs/getting-started/quickstart). diff --git a/docs/guides/development/override-clerk-types-interfaces.mdx b/docs/guides/development/override-clerk-types-interfaces.mdx index 0cedbf42f7..0eb48553c1 100644 --- a/docs/guides/development/override-clerk-types-interfaces.mdx +++ b/docs/guides/development/override-clerk-types-interfaces.mdx @@ -42,7 +42,7 @@ declare global { When defining custom types for Roles and Permissions: -- Custom Permissions are merged with [System Permissions](/docs/guides/organizations/roles-and-permissions#system-permissions) +- Custom Permissions are merged with [System Permissions](/docs/guides/organizations/control-access/roles-and-permissions#system-permissions) - Custom Roles completely replace default Roles (`org:admin` and `org:member`) ```tsx {{ filename: 'types/globals.d.ts' }} diff --git a/docs/guides/development/sdk-development/backend-only.mdx b/docs/guides/development/sdk-development/backend-only.mdx index 619689da03..d11819eb24 100644 --- a/docs/guides/development/sdk-development/backend-only.mdx +++ b/docs/guides/development/sdk-development/backend-only.mdx @@ -12,7 +12,7 @@ The source of truth for all BAPI endpoints is the [BAPI reference docs](/docs/re - User only needs to provide their [Secret Key](/docs/guides/development/sdk-development/terminology) - Centralized request authentication (e.g. in a middleware or plugin) - Give access to the instance of BAPI client (so that users can use all methods) -- User should be able to limit access to routes by checking for [Roles and Permissions](/docs/guides/organizations/roles-and-permissions) +- User should be able to limit access to routes by checking for [Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions) > [!IMPORTANT] > BAPI has [rate limits](/docs/guides/how-clerk-works/system-limits) to help protect users against brute-force attacks or stop abuse of Clerk's platform. Be sure to include a backoff mechanism into your fetching logic and respect the `Retry-After` header to gracefully handle any active rate limits. diff --git a/docs/guides/development/sdk-development/fullstack.mdx b/docs/guides/development/sdk-development/fullstack.mdx index 658f4ea202..f5eebe159e 100644 --- a/docs/guides/development/sdk-development/fullstack.mdx +++ b/docs/guides/development/sdk-development/fullstack.mdx @@ -14,7 +14,7 @@ A fullstack SDK combines the [frontend-only SDK](/docs/guides/development/sdk-de - User should be able to use [ClerkJS options](/docs/reference/javascript/clerk#clerk-options){{ target: '_blank' }} - Centralized request authentication (e.g. in a middleware or plugin) - Give access to the instance of [BAPI](/docs/guides/development/sdk-development/terminology) client (so that users can use all methods) -- User should be able to limit access to routes by checking for [Roles and Permissions](/docs/guides/organizations/roles-and-permissions) +- User should be able to limit access to routes by checking for [Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions) ## Optional features diff --git a/docs/guides/development/upgrading/upgrade-guides/core-2/backend.mdx b/docs/guides/development/upgrading/upgrade-guides/core-2/backend.mdx index effce20ccd..9db620be1e 100644 --- a/docs/guides/development/upgrading/upgrade-guides/core-2/backend.mdx +++ b/docs/guides/development/upgrading/upgrade-guides/core-2/backend.mdx @@ -686,7 +686,7 @@ As part of this major version, a number of previously deprecated props, argument - The `MembershipRole` type was replaced with `OrganizationCustomRoleKey` (related to [roles and permissions](/docs/guides/organizations/roles-and-permissions)). An example of where this type might be found: + The `MembershipRole` type was replaced with `OrganizationCustomRoleKey` (related to [roles and permissions](/docs/guides/organizations/control-access/roles-and-permissions)). An example of where this type might be found: ```js import { useAuth } from '@clerk/clerk-react' diff --git a/docs/guides/development/webhooks/syncing.mdx b/docs/guides/development/webhooks/syncing.mdx index e914eaaed7..4a097d21ee 100644 --- a/docs/guides/development/webhooks/syncing.mdx +++ b/docs/guides/development/webhooks/syncing.mdx @@ -5,16 +5,16 @@ description: Learn how to sync Clerk data to your app with webhooks. In some cases, you may want to sync Clerk's user table to a user table in your own database. Read the next few sections carefully to determine if this is the right approach for your app. diff --git a/docs/guides/organizations/invitations.mdx b/docs/guides/organizations/add-members/invitations.mdx similarity index 66% rename from docs/guides/organizations/invitations.mdx rename to docs/guides/organizations/add-members/invitations.mdx index 3136e774df..a6c4b5257f 100644 --- a/docs/guides/organizations/invitations.mdx +++ b/docs/guides/organizations/add-members/invitations.mdx @@ -1,41 +1,51 @@ --- -title: Invite users to your organization -description: Step-by-step guide on how to send, manage, and track user invitations within your multitenant SaaS, all using Clerk Organizations. +title: Invite users to your Organization +description: Send, manage, and track user invitations within your multi-tenant SaaS using Clerk Organizations. metadata: - title: Send and manage B2C/B2B organization invitations via Clerk + title: Send and manage Organization invitations via Clerk --- -Organization invitations allow you to add new members to your organization. When you send an invitation, Clerk sends an email to the invited user with a unique invitation link. When the user visits the organization invitation link, they will be redirected to the [Account Portal sign-in page](/docs/guides/customizing-clerk/account-portal#sign-in). If the user is already signed in, they will be redirected to your application's homepage (`/`). If you want to redirect the user to a specific page in your application, you can [specify a redirect URL when creating the invitation](#redirect-url). +Organization invitations let you add new members to your Organization. When you send an invitation, Clerk sends an email to the invited user with a unique invitation link. When the user visits the Organization invitation link, Clerk redirects them to the [Account Portal sign-in page](/docs/guides/customizing-clerk/account-portal#sign-in). If the user is already signed in, Clerk redirects them to your application's homepage (`/`). If you want to redirect the user to a specific page in your application, you can [specify a redirect URL when creating the invitation](#redirect-url). -By default, only admins can invite users to an organization. +By default, only [admins](/docs/guides/organizations/control-access/roles-and-permissions#default-roles) can invite users to an Organization. This feature requires that [**Email** is enabled](/docs/guides/configure/auth-strategies/sign-up-sign-in-options#email), as Clerk uses the user's email address to send the invitation. You can still disable **Email** as a sign-in option if you do not want users to be able to sign-in with their email address. To configure your application's **Email** settings, navigate to the [**User & authentication**](https://dashboard.clerk.com/~/user-authentication/user-and-authentication) page in the Clerk Dashboard. +## When to use invitations + +Invitations work well when you need precise control over who joins your Organization and which Role they receive. This approach fits scenarios where: + +- Teams are small and members are known in advance. +- Onboarding requires manual approval or review. +- Specific Roles need to be assigned during the invitation. + +If you want to streamline enrollment for users with company email addresses, consider [Verified Domains](/docs/guides/organizations/add-members/verified-domains), which can automatically invite users based on their email domain. If customers require centralized authentication through their Identity Provider, use [Enterprise SSO](/docs/guides/organizations/add-members/sso). + ## Create an invitation -Clerk's [prebuilt components](/docs/reference/components/overview) and [Account Portal pages](/docs/guides/customizing-clerk/account-portal) manage all organization invitation flows, including creating, managing, and accepting invitations. +Clerk's [prebuilt components](/docs/reference/components/overview) and [Account Portal pages](/docs/guides/customizing-clerk/account-portal) manage all Organization invitation flows, including creating, managing, and accepting invitations. However, if you want to build custom flows, see the following sections. ### Client-side -To create an organization invitation on the client-side, see the [dedicated guide](/docs/guides/development/custom-flows/organizations/manage-organization-invitations). Note that this uses the [`organizations.inviteMember()`](/docs/reference/javascript/organization#invite-member) method, which does not allow you to specify a redirect URL; it will always redirect to the Account Portal sign-in page. If you want to specify a redirect URL, you must create the invitation on the server-side. +To create an Organization invitation on the client-side, see the [dedicated guide](/docs/guides/development/custom-flows/organizations/manage-organization-invitations). Note that this uses the [`organizations.inviteMember()`](/docs/reference/javascript/organization#invite-member) method, which does not let you specify a redirect URL; it will always redirect to the Account Portal sign-in page. If you want to specify a redirect URL, you must create the invitation on the server-side. ### Server-side -To create organization invitations on the server-side, use the [Backend API](/docs/reference/backend-api/tag/organization-invitations/post/organizations/\{organization_id}/invitations){{ target: '_blank' }} either by using a cURL command or the [JS Backend SDK](/docs/js-backend/getting-started/quickstart). The JS Backend SDK is a wrapper around the Backend API that makes it easier to interact with the API. +To create Organization invitations on the server-side, use the [Backend API](/docs/reference/backend-api/tag/organization-invitations/post/organizations/\{organization_id}/invitations){{ target: '_blank' }} either by using a cURL command or the [JS Backend SDK](/docs/js-backend/getting-started/quickstart). The JS Backend SDK is a wrapper around the Backend API that makes it easier to interact with the API. Use the following tabs to see examples for each method. - The following example demonstrates how to create an organization invitation using cURL. + The following example demonstrates how to create an Organization invitation using cURL. - Your Secret Key is already injected into the code snippet. - - Replace the `org_123` with the ID of the organization you want to invite the user to. + - Replace the `org_123` with the ID of the Organization you want to invite the user to. - Replace the `user_123` with the ID of the user who is inviting the other user. - Replace the email address with the email address you want to invite. - Replace the `role` with the role you want to assign to the invited user. @@ -43,10 +53,10 @@ Use the following tabs to see examples for each method. - Replace `YOUR_SECRET_KEY` with your Clerk Secret Key. You can find your Secret Key on the [**API Keys**](https://dashboard.clerk.com/~/api-keys) page in the Clerk Dashboard. - - Replace the `org_123` with the ID of the organization you want to invite the user to. + - Replace the `org_123` with the ID of the Organization you want to invite the user to. - Replace the `user_123` with the ID of the user who is inviting the other user. - Replace the email address with the email address you want to invite. - - Replace the `role` with the role you want to assign to the invited user. + - Replace the `role` with the Role you want to assign to the invited user. ```bash {{ filename: 'terminal' }} @@ -83,11 +93,11 @@ Once the user visits the invitation link, they will be redirected to the page yo > [!TIP] > -> - To test redirect URLs in your development environment, pass your port. For example, `http://localhost:3000/accept-invitation`. +> To test redirect URLs in your development environment, pass your port. For example, `http://localhost:3000/accept-invitation`. ### Invitation metadata -You can also add metadata to an invitation when creating the invitation through the Backend API. Once the invited user signs up using the invitation link, the **invitation** metadata (`OrganizationInvitation.publicMetadata`) will be stored in the organization **membership's** metadata (`OrganizationMembership.publicMetadata`). You can find more information about organization membership metadata in the [Organization Membership](/docs/reference/javascript/types/organization-membership) docs. +You can also add metadata to an invitation when creating the invitation through the Backend API. Once the invited user signs up using the invitation link, Clerk stores the **invitation** metadata (`OrganizationInvitation.publicMetadata`) in the Organization **membership's** metadata (`OrganizationMembership.publicMetadata`). For more details on Organization membership metadata, see the [OrganizationMembership](/docs/reference/javascript/types/organization-membership) reference. To add metadata to an invitation, add the `public_metadata` parameter when creating the invitation. @@ -141,6 +151,15 @@ Use the following tabs to see examples for each method. - To use the JS Backend SDK to revoke an organization invitation, see the [`revokeOrganizationInvitation()`](/docs/reference/backend/organization/revoke-organization-invitation) reference documentation. + To use the JS Backend SDK to revoke an Organization invitation, see the [`revokeOrganizationInvitation()`](/docs/reference/backend/organization/revoke-organization-invitation) reference documentation. + +## Next steps + +Now that you know how to invite users to your Organization, you can: + +- [Configure Verified Domains](/docs/guides/organizations/add-members/verified-domains) to automatically invite users based on their email domain +- [Set up Enterprise SSO Connections](/docs/guides/organizations/add-members/sso) for centralized authentication through an Identity Provider +- [Set up Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions) to control what invited users can access +- [Add metadata to invitations](/docs/guides/organizations/metadata) for tracking or custom workflows diff --git a/docs/guides/organizations/add-members/sso.mdx b/docs/guides/organizations/add-members/sso.mdx new file mode 100644 index 0000000000..46f10bbbf8 --- /dev/null +++ b/docs/guides/organizations/add-members/sso.mdx @@ -0,0 +1,142 @@ +--- +title: Organization-level Enterprise SSO +description: Integrate as many Enterprise SSO methods within Clerk Organizations. Enable SAML SSO, OAuth/OIDC, and other secure MFA/single sign-on options for B2B SaaS apps. +metadata: + title: Set up Organization-level SAML and OIDC for B2B/B2C apps +--- + +Clerk provides Enterprise Single Sign-On (SSO) through a feature called [**Enterprise Connections**](/docs/guides/configure/auth-strategies/enterprise-connections/overview). You can enable Enterprise Connections for specific Organizations, allowing members to authenticate through their company's identity provider using SAML or OIDC protocols. + +When users sign up or sign in using an Organization's Enterprise Connection, Clerk automatically adds them as members of that Organization and assigns them the [default Role](/docs/guides/organizations/control-access/roles-and-permissions#the-default-role-for-members). This process is known as [Just-in-Time (JIT) provisioning](/docs/guides/configure/auth-strategies/enterprise-connections/jit-provisioning). + +## When to use Enterprise SSO + +Enterprise SSO works well when customers require centralized authentication through their Identity Provider (IdP). This approach fits scenarios where: + +- Enterprise customers have security requirements that mandate IdP-based authentication. +- IT teams need to manage user provisioning from a central location. +- Organizations want to maintain existing identity management workflows. + +If you need manual control over who joins and their [Roles](/docs/guides/organizations/control-access/roles-and-permissions), use [invitations](/docs/guides/organizations/add-members/invitations). If you want automatic enrollment without IdP requirements, use [Verified Domains](/docs/guides/organizations/add-members/verified-domains). + +## Common onboarding flows + +The timing of when you set up Enterprise SSO depends on how customers adopt your product. The two common approaches are to create the Organization and configure SSO before users sign in (top-down) or to let users start individually and add SSO later (bottom-up). + +### Organization created first (top-down approach) + +This flow is common for enterprise sales where the relationship is established before users access the application. + +1. [Create an Organization](/docs/guides/organizations/create-and-manage#create-an-organization) for your customer through the Clerk Dashboard. +1. Collaborate with the customer's IT administrator to obtain the necessary configuration details. +1. Configure the Enterprise SSO Connection for the Organization. +1. Invite users to the Organization, who can then sign in using Enterprise SSO. + +### User-initiated setup (bottom-up approach) + +This flow is common when individual users try the product before company-wide adoption. + +1. An end user signs up to evaluate your application, starting with an individual account. +1. After adopting the application, the user [creates an Organization](/docs/guides/organizations/create-and-manage#create-an-organization) for their company. +1. Configure Enterprise SSO for the Organization through the Clerk Dashboard. +1. All subsequent users from that Organization can now sign in using Enterprise SSO. + +## Add an Enterprise SSO connection for an Organization + +Clerk supports Enterprise SSO via [SAML](/docs/guides/configure/auth-strategies/enterprise-connections/overview#saml) or via the [OpenID Connect (OIDC) protocol](/docs/guides/configure/auth-strategies/enterprise-connections/overview#oidc), either through EASIE or by integrating with any OIDC-compatible provider. + +To add an Enterprise SSO Connection for an Organization, go to the [Enterprise Connections](/docs/guides/configure/auth-strategies/enterprise-connections/overview) docs and follow the appropriate guide based on the platform you want to use, such as the [Google SAML guide](/docs/guides/configure/auth-strategies/enterprise-connections/saml/google). When configuring the connection in the Clerk Dashboard, there will be an option to select the **Organization** for which you want to enable this connection. If you don't select an Organization, Clerk will add the connection for your entire application. + +> [!WARNING] +> A domain used for Enterprise SSO can't be used as a [Verified Domain](/docs/guides/organizations/add-members/verified-domains) for the same Organization. + +## Enforce Enterprise SSO by domain + +Clerk enforces Enterprise SSO connections on a per-domain basis in Organizations, enabling flexible access management: + +- Configure Enterprise SSO for your primary domain (e.g., `company.com`) to enforce Enterprise SSO authentication for employees. +- Add additional domains without Enterprise SSO for external collaborators (e.g., contractors, consultants). +- Each domain in an Organization can have different authentication requirements. + +## Remove a member from your Organization + +Users who joined through an Enterprise Connection cannot leave the Organization on their own. You can remove them through the Clerk Dashboard, the [Backend API](/docs/reference/backend-api/tag/organization-memberships/delete/organizations/\{organization_id}/memberships/\{user_id}){{ target: '_blank' }}, or by another member with the [manage members Permission](/docs/guides/organizations/control-access/roles-and-permissions#system-permissions) (`org:sys_memberships:manage`). However, the user will be added back to the Organization on next sign-in, unless they are removed from the IdP or the Enterprise Connection is no longer associated with the Organization. + +Removed users will automatically rejoin the Organization on their next sign-in unless you also remove them from the IdP or disconnect the Enterprise Connection. + +## Move an Enterprise Connection to a different Organization + +When you reassign an Enterprise Connection to a new Organization, existing members stay in the original Organization. They will automatically join the new Organization the next time they sign in. + +## Common SSO setup errors + +When setting up Enterprise SSO, you may encounter errors during the authentication flow. The type of error you see depends on which protocol your Enterprise Connection uses: + +- **SAML errors** occur when using SAML-based Enterprise Connections (e.g., Azure AD, Google Workspace, Okta). These errors typically relate to SAML assertion validation, attribute mapping, or domain configuration issues. +- **OAuth errors** occur when using OAuth/OIDC-based Enterprise Connections (e.g., custom OIDC providers, EASIE). These errors typically relate to authorization flows, token exchange, or user information retrieval. + +The following sections describe common error codes and how to resolve them. + +### `saml_user_attribute_missing` + +You will encounter this error when the user's account is missing a required attribute, for example, a `mail` attribute. + +**How to fix it:** + +Access your identity provider's configuration dashboard, navigate to your application's SAML settings or attribute mapping configuration, and ensure that the 'mail' attribute is properly mapped to the user's email address field. + +### `saml_response_relaystate_missing` + +You will encounter this error when the `RelayState` parameter is missing from the SAML Response. + +**How to fix it:** + +Check that your identity provider is correctly returning the RelayState parameter that was sent in the original request. + +### `saml_email_address_domain_mismatch` + +You will encounter this error when the email address domain of the user's account does not match the domain configured for the connection. + +**How to fix it:** + +1. Verify that the user is signing in with an email address that matches one of the allowed domains for this connection. +1. If you need to add additional domains to this connection, go to your Clerk Dashboard → SSO Connections → \[Your Connection] → Settings, and update the allowed domains. +1. Alternatively, ensure the user is accessing the correct SAML connection that matches their email domain. + +### `oauth_access_denied` + +You will encounter this error when the user clicks "Cancel" or "Deny" on the OAuth provider's authorization screen, or when the provider rejects the authorization request. + +**How to fix it:** + +1. Ask the user to try signing in again and ensure they approve the authorization request. +1. Verify in your Clerk Dashboard → SSO Connections that the OAuth application credentials (Client ID and Client Secret) are correctly configured. + +### `oauth_token_exchange_error` + +You will encounter this error when Clerk fails to exchange the authorization code for an access token. + +**How to fix it:** + +1. Verify in your Clerk Dashboard → SSO Connections that your OAuth application's Client ID and Client Secret are correctly configured and match the credentials from your OAuth provider's dashboard. +1. Ensure that the Redirect URI configured in your OAuth provider matches exactly what Clerk expects (including the protocol, domain, and path). + +### `oauth_fetch_user_error` + +You will encounter this error when Clerk is unable to retrieve the user's profile information from the OAuth provider. + +**How to fix it:** + +1. Verify that the OAuth scopes configured in your Clerk Dashboard → SSO Connections include the necessary permissions to read user profile information. +1. Ensure that the user info endpoint URL is correctly configured. + +## Next steps + +Now that you've set up Enterprise SSO, you can: + +- [Learn more about Enterprise Connections](/docs/guides/configure/auth-strategies/enterprise-connections/overview) for advanced configuration options +- [Understand JIT provisioning](/docs/guides/configure/auth-strategies/enterprise-connections/jit-provisioning) to customize how users are automatically added to Organizations +- [Configure Verified Domains](/docs/guides/organizations/add-members/verified-domains) for users who don't use SSO +- [Invite specific users](/docs/guides/organizations/add-members/invitations) to your Organization +- [Set up Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions) to control what SSO users can access +- [Configure default roles](/docs/guides/organizations/configure#default-roles) for users joining via SSO diff --git a/docs/guides/organizations/add-members/verified-domains.mdx b/docs/guides/organizations/add-members/verified-domains.mdx new file mode 100644 index 0000000000..bd7467493a --- /dev/null +++ b/docs/guides/organizations/add-members/verified-domains.mdx @@ -0,0 +1,100 @@ +--- +title: Verified Domains +description: Build Organization-specific or tenant-isolated authentication flows that only authorized users with matching domains can join, using Verified Domains within Clerk Organizations. +metadata: + title: Verified Domains within Clerk Organizations +--- + +Clerk's **Verified Domains** feature is useful for Organizations that want to restrict membership to users with specific email domains, and automatically invite or suggest users with that domain to join an Organization. For example, if the domain `@clerk.com` is verified, any user with an email address ending in `@clerk.com` can be automatically invited or be suggested to join an Organization with that domain. Clerk assigns users the [**Default** Role](/docs/guides/organizations/control-access/roles-and-permissions#the-default-role-for-members) set in the Organization settings page. + +A Verified Domain cannot be a disposable domain or common email provider. For example, you cannot create a Verified Domain for `@gmail.com`. + +> [!WARNING] +> A Verified Domain can't be added if it's already in use for the [Organization's Enterprise SSO](/docs/guides/organizations/add-members/sso). + +The easiest way to add and verify domains, and manage all settings related to Verified Domains is to use Clerk's [``](/docs/reference/components/organization/organization-switcher) component. + +## When to use Verified Domains + +Verified Domains work well when you want to streamline enrollment for users with company email addresses. This approach fits scenarios where: + +- Company-wide rollouts need automatic or suggested membership. +- Reducing onboarding friction for employees with approved email domains. +- Enrollment can happen based on email domain without manual approval. + +If you need precise control over specific people and their Roles, use [invitations](/docs/guides/organizations/add-members/invitations). If customers require authentication through their Identity Provider, use [Enterprise SSO](/docs/guides/organizations/add-members/sso). + +## Enable Verified Domains + +Enabling Verified Domains applies to all Organizations and cannot currently be managed on a per-Organization basis. + +In order to enable this feature: + +1. In the Clerk Dashboard, navigate to the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page. +1. In the **Organization options** section, toggle on **Enable verified domains**. +1. The following enrollment modes will appear that can be enabled for verified domains: + + - [**Automatic invitation**](#automatic-invitations) - Clerk automatically invites users to join the Organization when they sign up and they can join anytime. + - [**Automatic suggestion**](#automatic-suggestions) - Users receive a suggestion to request to join, but must be approved by an admin before they are able to join the Organization. + + When a user with the `org:sys_domains:manage` Permission has added and verified a domain, they can enable an enrollment mode. **Only one enrollment mode can be enabled for a Verified Domain at a time.** + +### Automatic invitations + +After sign-up, a user will receive an **invitation** for the Organization if their email's domain matches the Verified Domain. If your app uses the `` component, the user will see a notification on the component and also receive an email prompting them to accept the invitation. + +When they open the component, they will see a **Join** button next to the organization they were invited to. Selecting the button will accept the invitation and the user will instantly be added as a member of the Organization. + +### Automatic suggestions + +After sign-up, a user will receive a **suggestion** for the Organization if their email's domain matches the Verified Domain. If your app uses the `` component, the user will see a **Request to join** button next to the Organization. Selecting the button will send a [Membership Request](#membership-requests) to the Organization. + +### Membership Requests + +Membership Requests are requests from users who saw an Organization Suggestion and requested to join an Organization. Membership Requests are only available for Organizations that have the **Verified Domains** and **Automatic Suggestion** features enabled in both the Dashboard and for the specific domain. + +When a user sends an Organization Membership request, users with the `org:sys_memberships:manage` Permission (by default, admins) are notified through both: + +- A notification badge on the `` component. +- An email alert. + +Regardless of how they are notified, membership requests can only be reviewed and managed through the `` component. Selecting the notification badge will open the Organization management page, where the request appears under `Members > Requests`. A request must be approved before the user is added to the Organization. + +## Add and verify domains + +Any user with the `org:sys_domains:manage` Permission can add and verify domains under an Organization. By default, admins have this Permission. To add and verify domains in the [``](/docs/reference/components/organization/organization-switcher) component, select the **General** tab. There will be a **Verified domains** section. + +Domains can be verified through an email verification code sent to an email that matches the domain. If the user adding the domain already has a verified email using that domain in their account, Clerk will automatically verify the domain. + +An application instance may only have one Verified Domain of the same name, and an Organization may only have one domain of the same name (verified or unverified). + +You can create up to 10 domains per Organization to meet your needs. If you need more than 10 domains, [contact support](/contact/support){{ target: '_blank' }}. + +### Custom flow + +If Clerk's [``](/docs/reference/components/organization/organization-switcher) does not meet your specific needs or if you require more control over the logic, you can use the Clerk API to add and verify a domain and update the domain's enrollment mode. Here's an example of how you can do this: + +```tsx +const { organization, domains } = useOrganization() + +// create domain +const domain = await organization.createDomain('example.com') + +// prepare email verification +domain.prepareAffiliationVerification({ affiliationEmailAddress: 'foo@example.com' }) + +// attempt email verification +domain.attemptAffiliationVerification({ code: '123456' }) + +// update domain enrollment mode +domain.updateEnrollmentMode({ enrollmentMode: 'automatic_invitation' }) +``` + +## Next steps + +Now that you've configured Verified Domains, you can: + +- [Set up Enterprise SSO](/docs/guides/organizations/add-members/sso) for centralized authentication through an Identity Provider +- [Invite specific users](/docs/guides/organizations/add-members/invitations) who don't match your Verified Domain +- [Set up Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions) to control what auto-enrolled users can access +- [Configure default Roles](/docs/guides/organizations/configure#default-roles) for users joining via Verified Domains diff --git a/docs/guides/organizations/configure.mdx b/docs/guides/organizations/configure.mdx new file mode 100644 index 0000000000..c63cea0d1b --- /dev/null +++ b/docs/guides/organizations/configure.mdx @@ -0,0 +1,164 @@ +--- +title: Configure Organizations +description: Learn how to configure global Organization settings in the Clerk Dashboard, including pricing, membership limits, and optional features. +metadata: + title: Configure Organization settings in Clerk Dashboard +--- + +Global Organization settings control how Organizations work across your entire application. These settings determine who can create Organizations, how members join them, what Roles they receive, and which Features are available. You'll configure most of these when you first enable Organizations, though you can adjust them later as your needs evolve. + +## Enable Organizations + +Organizations are disabled by default. When you enable Organizations, Clerk offers two workspace models: + +- **Personal accounts disabled (default)**: Every user is required to belong to an Organization. All new and existing users will be prompted to create or join an Organization through the [session tasks flow](/docs/guides/configure/session-tasks) before they can access your application. + + > [!IMPORTANT] + > Personal Accounts being disabled by default was released on August 22, 2025. Applications created before this date will not see the **Allow Personal Accounts** setting, because Personal Accounts were enabled by default. + +- **Personal Accounts enabled**: Users can operate in their own individual workspace or join Organizations. They start in their Personal Account and can switch to Organizations using the [``](/docs/reference/components/organization/organization-switcher) component. + +Most B2B and multi-tenant applications leave Personal Accounts disabled. This ensures proper data isolation and team structure from the start. You should only enable Personal Accounts if your app serves both individual users and teams (like a tool that works for solo users but also has team features). + +To enable Organizations: + +1. In the Clerk Dashboard, navigate to the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page. +1. Select **Enable Organizations**. +1. In the modal, toggle **Allow Personal Accounts** based on your decision above. +1. Select **Enable**. + +Clerk measures Organizations by Monthly Active Organizations (MAOs). Refer to the [overview page](/docs/guides/organizations/overview#how-do-organizations-work) for pricing details and limits. + +## Organization settings + +Once Organizations are enabled, you can configure core features and behaviors, such as membership limits, Verified Domains, Organization slugs, and whether to allow Personal Accounts alongside Organizations. + +### Membership limits + +There is no limit to the number of Organizations a user can be a member of. + +Each Organization allows a maximum of 5 members by default. You can increase this limit as your customer base grows, or set different limits for individual Organizations if you have different pricing tiers. + +To change the membership limit for all Organizations in your application: + +1. In the Clerk Dashboard, navigate to the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page. +1. In the **Default membership limit** section, update the membership limit. + - **Free plan**: Allows a maximum of 5 members in an Organization + - **Pro plan**: Allows unlimited members in an Organization + +To change the membership limit for a specific Organization: + +1. In the Clerk Dashboard, select [**Organizations**](https://dashboard.clerk.com/~/organizations). +1. Select the Organization you want to update. +1. In the **Membership limit** section, update the limit for that specific Organization. + +### Allow Personal Accounts + +When enabling the Organizations feature, you were prompted to choose whether to allow Personal Accounts. This setting is disabled by default. Refer to the [section on enabling Organizations](#enable-organizations) above for a detailed explanation of how Personal Accounts work. + +You can change this setting after initial setup, which is useful if your product strategy evolves. For example, if you initially served only teams but now want to support individual users as well. + +To change this setting: + +1. In the Clerk Dashboard, navigate to the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page. +1. Toggle **Allow personal accounts**. + +### Verified Domains + +Verified Domains allow automatic or suggested Organization membership for users with specific email domains (like `@acme.com`). This is useful for company-wide rollouts where you want to streamline enrollment for employees with company email addresses. Members with the [`org:sys_domains:manage` System Permission](/docs/guides/organizations/control-access/roles-and-permissions#system-permissions) can manage Verified Domains and enrollment modes. + +Learn more about [Verified Domains](/docs/guides/organizations/add-members/verified-domains). + +### Organization slugs + +> [!IMPORTANT] +> Organization slugs are disabled by default for applications created after October 7, 2025. For applications created before this date, you can opt to disable it. + +Organization slugs are human-readable URL identifiers (like `acme-corp`) that help users reference which Organization they're working in. Enable this feature if you need Organization-specific URLs or if users frequently switch between multiple Organizations. + +You can also [use Organization slugs in your application's URLs](/docs/guides/organizations/org-slugs-in-urls). + +### Allow user-created Organizations + +By default, users can create Organizations in your application. You can restrict this if you prefer to manually provision Organizations. + +You can also override this Permission for specific users in their profile page under **User permissions**. + +Learn more about [creating Organizations](/docs/guides/organizations/create-and-manage). + +#### Organization creation limit + +{/* TODO: Come back to this. Is the max 100, or is it unlimited? By default, in the Clerk Dash, it says unlimited. But I thought Clerk caps each user to create up to 100 orgs per application instance */} + +When user-created Organizations are enabled, each user can create up to 100 Organizations by default. You can configure this to set a lower limit or allow unlimited Organizations. + +To change the default limit: + +1. In the Clerk Dashboard, navigate to the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page. +1. In the **Organization limit** section, choose between: + - **Users can create unlimited organizations** + - **Users can create a limited number of organizations** (specify the limit) + +If you need users to create more than 100 Organizations, [contact support](/contact/support){{ target: '_blank' }} to have the limit raised. + +To override this limit for a specific user: + +1. In the Clerk Dashboard, select [**Users**](https://dashboard.clerk.com/~/users). +1. Select the user you want to update. +1. In the **User permissions** section, configure their Organization creation limit. + +### Default roles + +When users create or join Organizations, they need to be assigned a role. These settings determine which roles are automatically assigned in different scenarios, whether someone is creating a new Organization or joining an existing one. + +#### Default role for members + +The default role for members is assigned to users when they join an Organization through invitations or Verified Domain enrollment. By default, this is set to [**Member**](/docs/guides/organizations/control-access/roles-and-permissions#default-roles). + +This role is used: + +- When sending invitations from the [``](/docs/reference/components/organization/organization-profile) component (pre-filled as default) +- When users auto-join via [Verified Domains](/docs/guides/organizations/add-members/verified-domains) +- As the suggested role for new Organization members + +To change the default role: + +1. In the Clerk Dashboard, navigate to the [**Roles & Permissions**](https://dashboard.clerk.com/~/organizations-settings/roles) page. +1. Select the three dots next to the role you want to set as default. +1. Choose **Set as Default role**. + +Learn more about [Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions). + +#### Creator's initial role + +When a user creates a new Organization, Clerk automatically adds them as its first member and assigns them the Organization's designated **Creator** Role. By default, that Role is [**Admin**](/docs/guides/organizations/control-access/roles-and-permissions#default-roles), giving them full control over the Organization they created. + +The Creator role must have at least these [System Permissions](/docs/guides/organizations/control-access/roles-and-permissions#system-permissions): + +- Manage members (`org:sys_memberships:manage`) +- Read members (`org:sys_memberships:read`) +- Delete Organization (`org:sys_profile:delete`) + +Learn more about the [Creator Role and how to reassign it](/docs/guides/organizations/control-access/roles-and-permissions#the-creator-role). + +### Allow new members to delete Organizations + +This setting controls whether Organization members can delete Organizations. + +By default, any member with the [`org:sys_profile:delete` System Permission](/docs/guides/organizations/control-access/roles-and-permissions#system-permissions) can delete an Organization. You can disable this if you want to prevent accidental data loss or require your own approval process before Organizations are removed. + +To change this setting: + +1. In the Clerk Dashboard, navigate to the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page. +1. Toggle **Allow new members to delete organizations**. + +> [!IMPORTANT] +> This setting only applies to newly created Organizations. Existing Organizations retain their current deletion settings. + +## Next steps + +Now that you've configured global settings, you can: + +- [Create your first Organization](/docs/guides/organizations/create-and-manage) and start adding members +- [Add members to your Organization](/docs/guides/organizations/add-members/invitations) with invitations, Verified Domains, or SSO +- [Configure access control](/docs/guides/organizations/control-access/roles-and-permissions) with Custom Roles and Permissions diff --git a/docs/guides/organizations/control-access/check-access.mdx b/docs/guides/organizations/control-access/check-access.mdx new file mode 100644 index 0000000000..a9ccb61b84 --- /dev/null +++ b/docs/guides/organizations/control-access/check-access.mdx @@ -0,0 +1,169 @@ +--- +title: Check Roles and Permissions with Authorization Checks +description: Limit access to content or entire routes based on a user's Organization Role or Permissions. +metadata: + title: Check Roles and Permissions in Organizations +--- + +Authorization checks are checks you perform in your code to determine the access rights and privileges of a user, ensuring they have the necessary Permissions to perform specific actions or access certain content. These checks are essential for protecting sensitive data, gating premium features, and ensuring users stay within their allowed scope of access. + +Within Organizations, authorization checks can be performed by checking a user's Roles or Custom Permissions. Roles like `org:admin` determine a user's level of access within an Organization, while Custom Permissions like `org:invoices:create` provide fine-grained control over specific features and actions. + +## Examples + +For examples on how to perform authorization checks, see the [guide on authorization checks](/docs/guides/secure/authorization-checks). + + + + You can protect content and even entire routes based on Organization membership, Roles, and Permissions by performing [authorization checks](!authorization-check). + + In the following example, the page is restricted to authenticated users, users who have the `org:admin` Role, and users who belong to the `Acme Corp` Organization. + + - The [`Auth`](/docs/reference/backend/types/auth-object) object is used to access the `isSignedIn` property and `has()` method. + - The `isSignedIn` property is used to check if the user is signed in. + - The `has()` method is used to check if the user has the `org:admin` Role. + - The [`useOrganization()`](/docs/reference/hooks/use-organization) hook is used to access the organization data. + - The Organization name is checked to ensure it matches the required Organization name. If a user is not in the required Organization, the page will display a message and the [``](/docs/reference/components/organization/organization-switcher) component will be rendered to allow the user to switch to the required Organization. + + ```tsx {{ filename: 'app/protected/page.tsx' }} + 'use client' + import { OrganizationSwitcher, useAuth, useOrganization } from '@clerk/nextjs' + + export default function Page() { + // The `useAuth()` hook gives you access to properties like `isSignedIn` and `has()` + const { isSignedIn, has } = useAuth() + const { organization } = useOrganization() + + // Check if the user is authenticated + if (!isSignedIn) { + return

You must be signed in to access this page.

+ } + + // Check if there is an Active Organization + if (!organization) { + return ( + <> +

Set an Active Organization to access this page.

+ + + ) + } + + // Check if the user has the `org:admin` Role + if (!has({ role: 'org:admin' })) { + return

You must be an admin to access this page.

+ } + + // Check if Organization name matches (e.g., "Acme Corp") + const requiredOrgName = 'Acme Corp' + if (organization.name !== requiredOrgName) { + return ( + <> +

+ This page is only accessible in the {requiredOrgName} Organization. + Switch to the {requiredOrgName} Organization to access this page. +

+ + + ) + } + + return ( +

+ You are currently signed in as an admin in the{' '} + {organization.name} Organization. +

+ ) + } + ``` + + For more examples on how to perform authorization checks, see the [dedicated guide](/docs/guides/secure/authorization-checks). +
+ + + You can protect content and even entire routes based on Organization membership, Roles, and Permissions by performing [authorization checks](!authorization-check). + + In the following example, the page is restricted to authenticated users, users who have the `org:admin` Role, and users who belong to the `Acme Corp` Organization. + + - The [`Auth`](/docs/reference/backend/types/auth-object) object is used to access the `isAuthenticated` and `orgId` properties, as well as the `has()` method. + - The `isAuthenticated` property is used to check if the user is authenticated. + - The `orgId` property is used to check if there is an Active Organization. + - The `has()` method is used to check if the user has the `org:admin` Role. + - To fetch the Organization server-side, the [`clerkClient()`](/docs/reference/nextjs/overview#clerk-client) helper is used to access the [`getOrganization()`](/docs/reference/backend/organization/get-organization) method. + - The Organization name is checked to ensure it matches the required Organization name. If a user is not in the required Organization, the page will display a message and the [``](/docs/reference/components/organization/organization-switcher) component will be rendered to allow the user to switch to the required Organization. + + This example is written for Next.js App Router, but can be adapted to other frameworks by using the appropriate method for accessing the [`Auth` object](/docs/reference/backend/types/auth-object), and the appropriate initialization for `clerkClient()`. + + ```tsx {{ filename: 'app/protected/page.tsx' }} + import { auth, clerkClient } from '@clerk/nextjs/server' + import { OrganizationSwitcher } from '@clerk/nextjs' + + export default async function Page() { + // The `Auth` object gives you access to properties like `isAuthenticated` and `userId` + // Accessing the `Auth` object differs depending on the SDK you're using + // https://clerk.com/docs/reference/backend/types/auth-object#how-to-access-the-auth-object + const { isAuthenticated, orgId, has } = await auth() + + // Check if the user is authenticated + if (!isAuthenticated) { + return

You must be signed in to access this page.

+ } + + // Check if there is an Active Organization + if (!orgId) { + return ( + <> +

Set an Active Organization to access this page.

+ + + ) + } + + // Check if the user has the `org:admin` Role + if (!has({ role: 'org:admin' })) { + return

You must be an admin to access this page.

+ } + + // To fetch the Active Organization server-side, + // first initialize the JS Backend SDK. + // This varies depending on the SDK you're using + // https://clerk.com/docs/js-backend/getting-started/quickstart + // Then use the `clerkClient()` to access the `getOrganization()` method + const client = await clerkClient() + const organization = await client.organizations.getOrganization({ organizationId: orgId }) + + // Check if Organization name matches (e.g., "Acme Corp") + const requiredOrgName = 'Acme Corp' + if (organization.name !== requiredOrgName) { + return ( + <> +

+ This page is only accessible in the {requiredOrgName} Organization. + Switch to the {requiredOrgName} Organization to access this page. +

+ + + ) + } + + return ( +

+ You are currently signed in as an admin in the{' '} + {organization.name} Organization. +

+ ) + } + ``` + + For more examples on how to perform authorization checks, see the [dedicated guide](/docs/guides/secure/authorization-checks). +
+
+ +## Next steps + +Now that you know how to check Roles and Permissions, you can: + +- [Read the complete authorization checks guide](/docs/guides/secure/authorization-checks) +- [Learn how to check Features and Plans](/docs/guides/billing/for-b2b#control-access-with-features-plans-and-permissions) for Subscription-based applications +- [Set up custom Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions) to define your access control model +- [Configure default Roles](/docs/guides/organizations/configure#default-roles) for new Organization members diff --git a/docs/guides/organizations/control-access/roles-and-permissions.mdx b/docs/guides/organizations/control-access/roles-and-permissions.mdx new file mode 100644 index 0000000000..79600dc851 --- /dev/null +++ b/docs/guides/organizations/control-access/roles-and-permissions.mdx @@ -0,0 +1,148 @@ +--- +title: Roles and Permissions +description: Implement Role-Based Access Control (RBAC) in your application. Set custom Roles, assign privileges, and control access to resources using Clerk Organizations. +metadata: + title: B2B/B2C Roles and Permissions with Clerk Organizations +--- + + + +Roles and Permissions let you control who can access specific resources and perform certain actions within each Organization. Clerk provides two default Roles - **admin** and **member** - that cover most common use cases. You can also create custom Roles and fine-grained Permissions that fit your application's specific features and team setup. + +## Roles + +Each Role defines what users can do and access within an Organization. You can extend a Role's capabilities by adding [Permissions](#permissions). + +### Default Roles + +When users create or join Organizations, they need to be assigned a Role. These settings determine which Roles are automatically assigned in different scenarios, whether someone is creating a new Organization or joining an existing one. + +For each instance, there are currently two default Roles: + +- **Admin (`org:admin`)** - Offers full access to Organization resources. Members with the admin Role have all of the [System Permissions](#system-permissions). They can fully manage the Organization and Organization memberships. +- **Member (`org:member`)** - Offers limited access to Organization resources. Access to Organization resources is limited to the "Read members" and "Read billing" Permissions only, by default. They cannot manage the Organization and Organization memberships, but they can view information about other members in it. + +### The **Creator** Role + +When a user creates a new Organization, Clerk automatically adds them as its first member and assigns them the Organization's designated **Creator** Role. By default, that Role is `org:admin`. + +You cannot delete an Organization Role if it's used as the Organization's **Creator** Role. But, you _can_ reassign the **Creator** Role to any other Role with the right Permissions. For example, if you want to delete the `admin` Role, you will have to assign another Role as the **Creator** Role. + +The **Creator** Role must _at least_ have the following [System Permissions](#system-permissions): + +- Manage members (`org:sys_memberships:manage`) +- Read members (`org:sys_memberships:read`) +- Delete Organization (`org:sys_profile:delete`) + +To reassign the **Creator** Role: + +1. In the Clerk Dashboard, navigate to [**Roles & Permissions**](https://dashboard.clerk.com/~/organizations-settings/roles). +1. [Create a new Role](#custom-roles) or use an existing Role from the list. +1. Ensure that **Manage members**, **Read members**, and **Delete Organization** System Permissions are selected for the Role. +1. Open the three dots icon for the Role. +1. From the dropdown, select the **Set as Creator role** option. + +### The **Default** Role for members + +New Organization members are initially assigned the **Default** Role. By default, that Role is `org:member`. This Role is used as a pre-filled default in `` invitations and for Organization enrollment with [Verified Domains](/docs/guides/organizations/add-members/verified-domains). + +You cannot delete an Organization Role if it's used as the Organization's **Default** Role. But, you _can_ reassign the **Default** Role to any other Role. + +To reassign the **Default** Role: + +1. In the Clerk Dashboard, navigate to [**Roles & Permissions**](https://dashboard.clerk.com/~/organizations-settings/roles). +1. [Create a new Role](#custom-roles) or use an existing Role from the list. +1. Select the three dots next to the Role you want to set as default. +1. From the dropdown, select the **Set as Default role** option. + +### Custom Roles + +You can create up to 10 custom Organization Roles per application instance to meet your application needs. If you need more than 10 Roles, [contact support](/contact/support){{ target: '_blank' }}. + +Custom Roles can be granted Permissions and access. For example, you can create a new Role of **Billing** (`org:billing`) which can be used to group users who belong to a specific department of the Organization and have permission to manage credit card information, invoices, and other resources related to billing. + +To create a new Role: + +1. In the Clerk Dashboard, navigate to [**Roles & Permissions**](https://dashboard.clerk.com/~/organizations-settings/roles) +1. Select **Add role**. +1. Give the Role a name, a key to reference it by, and a description. The final key will follow the format `org:`. +1. Select **Save**. + +### Change a user's Role + +You can change a user's Role in the Clerk Dashboard, or in your application using the [``](/docs/reference/components/organization/organization-switcher) component. + +To change a user's Role in the Clerk Dashboard: + +1. In the Clerk Dashboard, select [**Organizations**](https://dashboard.clerk.com/~/organizations) and select an organization. +1. Select the **Members** tab. +1. In the list of members, find the one whose Role you want to change. +1. Select another Role from their Role dropdown. + +### Delete a Role + +You cannot delete a Role that is still assigned to members of an Organization. Change the members to a different Role before completing the following steps. + +1. In the Clerk Dashboard, navigate to [**Roles & Permissions**](https://dashboard.clerk.com/~/organizations-settings/roles). +1. Select the three dots icon next to the Role. +1. Select **Delete role**. + +## Permissions + +Permissions grant users privileged access to resources and operations, like creating and deleting. Clerk supports two types of Permissions: **System Permissions** and **Custom Permissions**. + +### System Permissions + +Clerk provides a set of System Permissions that power [Clerk's Frontend API](/docs/reference/frontend-api){{ target: '_blank' }} and [organization-related Clerk components](/docs/reference/components/overview). These Permissions serve as the baseline required for Clerk to operate effectively. + +Clerk's System Permissions consist of the following: + +- Manage Organization (`org:sys_profile:manage`) +- Delete Organization (`org:sys_profile:delete`) +- Read members (`org:sys_memberships:read`) +- Manage members (`org:sys_memberships:manage`) +- Read domains (`org:sys_domains:read`) +- Manage domains (`org:sys_domains:manage`) +- Read billing (`org:sys_billing:read`) +- Manage billing (`org:sys_billing:manage`) + +You can assign these System Permissions to any Role. + +> [!WARNING] +> System Permissions aren't included in [session claims](/docs/guides/sessions/session-tokens#default-claims). If you need to check Permissions on the server-side, you must [create Custom Permissions](#custom-permissions) for authorization checks in your application code. + +### Custom Permissions + +Custom Permissions let you define fine-tuned access control within your Organization. Each Permission is tied to a Feature, and can be assigned to one or more Roles. To create a Custom Permission, you must first create a Role (e.g. **sales**) and a Feature within that Role (e.g. **invoices**). Once both exist, you can define specific Permissions (e.g. **create**) related to that Feature. To assign a Custom Permission to a user, you must assign the user to the Role that has the Permission. + +To create a new Permission: + +1. In the Clerk Dashboard, navigate to [**Roles & Permissions**](https://dashboard.clerk.com/~/organizations-settings/roles). +1. [Create a new Role](#custom-roles) or use an existing Role from the list. +1. Under **Custom permissions**, select **Create permission** under the Feature you want to create the Permission for. If there are no Features, you'll need to create a new one first. Select **Create feature** and fill in the required fields. Once finished, the newly created Feature will appear in the list, and the **Create permission** button will appear. +1. Give the Permission a name, a key to reference it by, and a description. The final key will follow the format `org::`. + > [!NOTE] + > Common Permission values could be: + > + > - `create` — to allow creating resources + > - `read` — to allow reading/viewing resources + > - `update/manage` — to allow updating/editing resources + > - `delete` — to allow deleting resources + > + > For example, you could create a new Permission called **Create invoices** (`org:invoices:create`) which allows only users with this Permission to edit invoices. Then, you could assign this Permission to a Role, or multiple Roles, such as **Billing** (`org:billing`) or **Sales** (`org:sales`). +1. Select **Create permission**. + +You can also create a Custom Permission by navigating to the [**Features**](https://dashboard.clerk.com/~/features) tab in the Clerk Dashboard. + +## Verify a user's Role or Permission + +It's best practice to always verify whether or not a user is **authorized** to access sensitive information, important content, or exclusive features. **Authorization** is the process of determining the access rights and privileges of a user, ensuring they have the necessary Permissions to perform specific actions. To perform authorization checks using a user's Role or Permission, see the [guide on authorizing users](/docs/guides/secure/authorization-checks). + +## Next steps + +Now that you've set up Roles and Permissions, you can: + +- [Perform authorization checks](/docs/guides/secure/authorization-checks) to limit access to content or entire routes based on a user's Role or Permissions +- [Learn how to automatically invite users to an Organization based on their email domain](/docs/guides/organizations/add-members/verified-domains) +- [Learn how to manually invite users to an Organization](/docs/guides/organizations/add-members/invitations) +- [Learn how to automatically add users to an Organization through Enterprise SSO](/docs/guides/organizations/add-members/sso) diff --git a/docs/guides/organizations/create-and-manage.mdx b/docs/guides/organizations/create-and-manage.mdx new file mode 100644 index 0000000000..e8694b77a5 --- /dev/null +++ b/docs/guides/organizations/create-and-manage.mdx @@ -0,0 +1,61 @@ +--- +title: Create and manage Organizations +description: Learn how to create and manage individual Organizations in the Clerk Dashboard and in your application. +metadata: + title: Create and manage Organizations with Clerk +--- + +Organizations can be created and managed either **in the Clerk Dashboard** or **in your application**. This guide covers working with individual Organizations. For global settings that affect all Organizations in your application (like enabling Organizations, setting default Roles, or configuring memberships), refer to the [dedicated guide](/docs/guides/organizations/configure). + +## Create an Organization + +Organizations can be created in the Clerk Dashboard or in your application. The number of Organizations you can create depends on your [Monthly Active Organization (MAO) limits](/docs/guides/organizations/overview#how-do-organizations-work). + +### Create an Organization in the Clerk Dashboard + +To create an Organization in the Clerk Dashboard, navigate to the [**Organizations**](https://dashboard.clerk.com/~/organizations) page and select the **Create Organization** button. + +### Create an Organization in your application + +By default, [users have permission to create Organizations within your application](/docs/guides/organizations/configure#allow-user-created-organizations). When a user creates an Organization, they become the Organization's [admin](/docs/guides/organizations/control-access/roles-and-permissions#default-roles) with full control over settings, members, and Permissions. + +**Default limits**: Each user can create up to 100 Organizations. To change creation permissions or limits, see the [dedicated guide](/docs/guides/organizations/configure#allow-user-created-organizations). + +The easiest way to allow users to create Organizations is to use the [``](/docs/reference/components/organization/create-organization) and/or [``](/docs/reference/components/organization/organization-switcher) components. The `` component is more comprehensive, as it handles all Organization flows including creating, switching, and managing an Organization. + +If the prebuilt components don't meet your needs, you can build [custom flows](/docs/guides/development/custom-flows/overview) using the Clerk API. + +## Manage Organizations + +As an application owner, you can manage all Organizations in your application, both those created by you and those created by your users. You can view, update, and delete any Organization, as well as manage its members and settings. + +### Manage Organizations in the Clerk Dashboard + +To manage an Organization in the Clerk Dashboard, navigate to the [**Organizations**](https://dashboard.clerk.com/~/organizations) page. Select a specific Organization to view its details, members, invitations, subscriptions, payments, and settings. + +### Manage Organizations in your application + +For managing Organizations in your application, Clerk provides prebuilt components that handle Organization management flows: + +- [``](/docs/reference/components/organization/organization-profile) - A profile page for the user's currently active Organization where they can update settings and manage members. +- [``](/docs/reference/components/organization/organization-switcher) - A dropdown menu that handles all Organization flows, including switching between Organizations and managing the active Organization's profile. +- [``](/docs/reference/components/organization/organization-list) - A list of Organizations that a user is a member of, with options to switch between them. + +If the prebuilt components don't meet your needs, you can build [custom flows](/docs/guides/development/custom-flows/overview) using the Clerk API. + +## Switch between Organizations + +Users who belong to multiple Organizations can switch between them at any time. The currently selected Organization is called the active Organization. + +The [``](/docs/reference/components/organization/organization-switcher) component provides the easiest way for users to switch between Organizations. If you need more control over the switching logic, you can use the `setActive()` method from the [`useOrganizationList()`](/docs/reference/hooks/use-organization-list) hook, or access it directly from the [`Clerk`](/docs/reference/javascript/clerk#set-active) object. + +If [Personal Accounts are enabled](/docs/guides/organizations/configure#allow-personal-accounts), users can switch to their Personal Account using the `` component. + +## Next steps + +Now that you know how to create and manage Organizations, you can: + +- [Add custom data with Organization metadata](/docs/guides/organizations/metadata) +- [Use Organization slugs in URLs](/docs/guides/organizations/org-slugs-in-urls) for tenant-specific routing +- [Invite members to Organizations](/docs/guides/organizations/add-members/invitations) +- [Set up Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions) diff --git a/docs/guides/organizations/getting-started.astro.mdx b/docs/guides/organizations/getting-started.astro.mdx new file mode 100644 index 0000000000..036ffc90bb --- /dev/null +++ b/docs/guides/organizations/getting-started.astro.mdx @@ -0,0 +1,266 @@ +--- +title: Get started with Organizations and Astro +description: Create and manage organizations in your Astro app in this guided tutorial. +sdk: astro +--- + + + +Organizations let you group users with Roles and Permissions, enabling you to build multi-tenant B2B apps like Slack (workspaces), Linear (teams), or Vercel (projects) where users can switch between different team contexts. This tutorial will demonstrate how to add Organizations, create and switch Organizations, and protect routes by Organization and Roles. + + + ## Add `` to your app + + The `` component is the easiest way to let users create, switch between, and manage Organizations. It's recommended to place it in your app's header or navigation so it's always accessible to your users. For example: + + ```astro {{ filename: 'src/layouts/Layout.astro', fold: [[27, 34]] }} + --- + import { + SignedIn, + SignedOut, + UserButton, + SignInButton, + + OrganizationSwitcher, + } from '@clerk/astro/components' + --- + + + + + + + + + Astro Basics + + +
+ + + + + + + + +
+ + + + + + ``` + + ## Access Organization data + + + + To access information about the currently [Active Organization](!active-organization) on the server-side, use [`clerkClient()`](/docs/reference/astro/overview#example-use-clerk-client-to-get-a-users-information) to call the [`getOrganization()`](/docs/reference/backend/organization/get-organization) method, which returns the Backend [`Organization`](/docs/reference/backend/types/backend-organization) object. You'll need to pass an `orgId`, which you can access from the [`Auth`](/docs/reference/backend/types/auth-object) object. + + ```astro {{ filename: 'src/pages/index.astro' }} + --- + import Layout from '../layouts/Layout.astro' + import { SignedIn, SignedOut } from '@clerk/astro/components' + import { clerkClient } from '@clerk/astro/server' + + // Use the `locals.auth()` local to access the `Auth` object + // https://clerk.com/docs/reference/backend/types/auth-object + const { isAuthenticated, orgId, orgRole } = Astro.locals.auth() + + let organization = null + if (isAuthenticated && orgId) { + organization = await clerkClient(Astro).organizations.getOrganization({ organizationId: orgId }) + } + --- + + + +

Sign in to try Clerk out!

+
+ + { + organization && ( +
+

+ Welcome to the {organization.name} organization +

+

+ Your role in this organization: {orgRole} +

+
+ ) + } +
+
+ ``` +
+ + + To access information about the currently [Active Organization](!active-organization) on the client-side, use the [`$organizationStore`](/docs/reference/astro/client-side-helpers/organization-store) store, which returns the [`Organization`](/docs/reference/javascript/organization) object. This requires that you've [set up your Astro app to be integrated with React](/docs/reference/astro/react). + + ```tsx {{ filename: 'components/Home.tsx' }} + import { useStore } from '@nanostores/react' + import { $organizationStore } from '@clerk/astro/client' + + export default function Home() { + const organization = useStore($organizationStore) + + // Handle loading state + if (organization === undefined) return

Loading...

+ + // Handle no Active Organization state + if (organization === null) return

Set an Active Organization to access this page.

+ + return

This current Organization is {organization.name}

+ } + ``` +
+
+ + ## Visit your app + + Run your project with the following command: + + ```npm + npm run dev + ``` + + Visit your app locally at [`localhost:4321`](http://localhost:4321). + + ### Enable Organizations + + When prompted, select **Enable Organizations**. + + ### Create first user and Organization + + You must sign in to use Organizations. When prompted, select **Sign in to continue**. Then, authenticate to create your first user. + + Since you selected disabled personal accounts when you enabled Organizations, every user must be in at least one Organization. [Clerk will prompt you](!choose-organization) to create an Organization for your user. + + ## Create and switch Organizations + + At this point, Clerk should have redirected you to a page with the [``](/docs/reference/components/organization/organization-switcher) component. This component allows you to create, switch between, and manage Organizations. + + 1. Select the `` component, then **Create an organization**. + 1. Enter `Acme Corp` as the Organization name. + 1. Invite users to your Organization and select their Role. + + ## Protect routes by Organization and Roles + + You can protect content and even entire routes based on Organization membership, Roles, and Permissions by performing [authorization checks](!authorization-check). + + In the following example, the page is protected from unauthenticated users, users that don't have the `org:admin` Role, and users that are not in the `Acme Corp` Organization. It uses the [`has()`](/docs/reference/backend/types/auth-object#has) helper to perform the authorization check for the `org:admin` Role. + + + + ```astro {{ filename: 'src/pages/protected.astro' }} + --- + import Layout from '../layouts/Layout.astro' + import { clerkClient } from '@clerk/astro/server' + + const { isAuthenticated, has, orgId, orgRole } = Astro.locals.auth() + + const requiredOrgName = 'Acme Corp' + + let organization = null + if (isAuthenticated && orgId) { + organization = await clerkClient(Astro).organizations.getOrganization({ organizationId: orgId }) + } + --- + + + + {!isAuthenticated &&

You must be signed in to access this page.

} + + + {!organization &&

Set an Active Organization to access this page.

} + + + {!has({ role: 'org:admin' }) &&

You must be an admin to access this page.

} + + + { + organization && + (organization.name !== requiredOrgName ? ( +

+ This page is only accessible in the {requiredOrgName} Organization. + Switch to the {requiredOrgName} Organization to access this page. +

+ ) : ( +

+ You are currently signed in as an admin in the{' '} + {organization.name} Organization. +

+ )) + } +
+ ``` +
+ + + ```tsx {{ filename: 'components/Home.tsx' }} + import { useStore } from '@nanostores/react' + import { $organizationStore } from '@clerk/astro/client' + import { useAuth } from '@clerk/astro/react' + + export default function Home() { + const organization = useStore($organizationStore) + const { has, isSignedIn } = useAuth() + const requiredOrgName = 'Acme Corp' + + if (!isSignedIn) return

You must be signed in to access this page.

+ + // Handle loading state + if (organization === undefined) return

Loading...

+ + // Handle no Active Organization state + if (organization === null) return

Set an Active Organization to access this page.

+ + // Check if user has the required Role to access this page + if (!has({ role: 'org:admin' })) { + return

You must be an admin to access this page.

+ } + + // Check if Organization name matches (e.g. 'Acme Corp') + if (organization.name !== requiredOrgName) { + return ( +

+ This page is only accessible in the {requiredOrgName} Organization. Switch + to the {requiredOrgName} Organization to access this page. +

+ ) + } + + return ( +

+ You are currently signed in as an admin in the{' '} + {organization.name} Organization. +

+ ) + } + ``` +
+
+ + Navigate to [`localhost:4321/protected`](localhost:4321/protected). You should see a green message confirming you are an admin in `Acme Corp`. Use the `` to switch Organizations or rename the Organization to show the red message. + + Learn more about protecting routes and checking Organization Roles in the [guide on authorization checks](/docs/guides/organizations/control-access/roles-and-permissions). + + ## It's time to build your B2B SaaS! + + +
diff --git a/docs/guides/organizations/getting-started.mdx b/docs/guides/organizations/getting-started.mdx new file mode 100644 index 0000000000..b8fc5ff752 --- /dev/null +++ b/docs/guides/organizations/getting-started.mdx @@ -0,0 +1,291 @@ +--- +title: Get started with Organizations and Next.js +description: Create and manage Organizations in your Next.js app in this guided tutorial. +sdk: nextjs +--- + + + +Organizations let you group users with Roles and Permissions, enabling you to build multi-tenant B2B apps like Slack (workspaces), Linear (teams), or Vercel (projects) where users can switch between different team contexts. This tutorial will demonstrate how to add Organizations, create and switch Organizations, and protect routes by Organization and Roles. + + + ## Add `` to your app + + The `` component is the easiest way to let users create, switch between, and manage Organizations. It's recommended to place it in your app's header or navigation so it's always accessible to your users. For example: + + ```tsx {{ filename: 'app/layout.tsx', fold: [[11, 28]] }} + import type { Metadata } from 'next' + import { + ClerkProvider, + SignInButton, + SignUpButton, + SignedIn, + SignedOut, + UserButton, + + OrganizationSwitcher, + } from '@clerk/nextjs' + import { Geist, Geist_Mono } from 'next/font/google' + import './globals.css' + + const geistSans = Geist({ + variable: '--font-geist-sans', + subsets: ['latin'], + }) + + const geistMono = Geist_Mono({ + variable: '--font-geist-mono', + subsets: ['latin'], + }) + + export const metadata: Metadata = { + title: 'Clerk Next.js Quickstart', + description: 'Generated by create next app', + } + + export default function RootLayout({ + children, + }: Readonly<{ + children: React.ReactNode + }>) { + return ( + + + +
+ + + + + + + + + + + +
+ {children} + + +
+ ) + } + ``` + + ## Access Organization data + + + + To access information about the currently [Active Organization](!active-organization) on the server-side, use [`clerkClient()`](/docs/reference/nextjs/overview#clerk-client) to call the [`getOrganization()`](/docs/reference/backend/organization/get-organization) method, which returns the Backend [`Organization`](/docs/reference/backend/types/backend-organization) object. You'll need to pass an `orgId`, which you can access from the [`Auth`](/docs/reference/backend/types/auth-object) object. + + ```tsx + import { auth, clerkClient } from '@clerk/nextjs/server' + import { OrganizationSwitcher } from '@clerk/nextjs' + + export default async function Page() { + // Use `auth()` to access the `Auth` object + // https://clerk.com/docs/reference/backend/types/auth-object + const { isAuthenticated, orgId, orgRole } = await auth() + + // Check if user is authenticated + if (!isAuthenticated) return

You must be signed in to access this page.

+ + // Check if there is an Active Organization + if (!orgId) return

Set an Active Organization to access this page.

+ + // Initialize the JS Backend SDK + // This varies depending on the SDK you're using + // https://clerk.com/docs/js-backend/getting-started/quickstart + const client = await clerkClient() + + // Use the `getOrganization()` method to get the Backend `Organization` object + const organization = await client.organizations.getOrganization({ organizationId: orgId }) + + return ( +
+

+ Welcome to the {organization.name} organization +

+

+ Your role in this organization: {orgRole} +

+
+ ) + } + ``` +
+ + + Use the [`useOrganization()`](/docs/reference/hooks/use-organization) hook to access information about the currently [Active Organization](!active-organization). Use the [`useOrganizationList()`](/docs/reference/hooks/use-organization-list) hook to access information about the current user's organization memberships. + + ```tsx {{ filename: 'app/page.tsx' }} + 'use client' + + import { useOrganization, useOrganizationList } from '@clerk/nextjs' + + export default function Page() { + const { organization } = useOrganization() + const { userMemberships } = useOrganizationList({ + userMemberships: true, + }) + + return ( +
+

+ Welcome to the {organization?.name} organization +

+

+ Your role in this organization:{' '} + + {/* Find the organization membership that matches the + currently active organization and return the role */} + { + userMemberships?.data?.find( + (membership) => membership.organization.id === organization?.id, + )?.role + } + +

+
+ ) + } + ``` +
+
+ + ## Visit your app + + Run your project with the following command: + + ```npm + npm run dev + ``` + + Visit your app locally at [`localhost:3000`](http://localhost:3000). + + ### Enable Organizations + + When prompted, select **Enable Organizations**. + + ### Create first user and Organization + + You must sign in to use Organizations. When prompted, select **Sign in to continue**. Then, authenticate to create your first user. + + Since you selected disabled Personal Accounts when you enabled Organizations, every user must be in at least one Organization. [Clerk will prompt you](!choose-organization) to create an Organization for your user. + + ## Create and switch Organizations + + At this point, Clerk should have redirected you to a page with the [``](/docs/reference/components/organization/organization-switcher) component. This component allows you to create, switch between, and manage organizations. + + 1. Select the `` component, then **Create an organization**. + 1. Enter `Acme Corp` as the Organization name. + 1. Invite users to your Organization and select their Role. + + ## Protect routes by Organization and Roles + + You can protect content and even entire routes based on Organization membership, Roles, and Permissions by performing [authorization checks](!authorization-check). + + In the following example, the page is protected from unauthenticated users, users that don't have the `org:admin` Role, and users that are not in the `Acme Corp` Organization. + + + + ```tsx {{ filename: 'app/protected/page.tsx' }} + import { auth, clerkClient } from '@clerk/nextjs/server' + import { OrganizationSwitcher } from '@clerk/nextjs' + + export default async function Page() { + const { isAuthenticated, orgId, has } = await auth() + + // Check if the user is authenticated + if (!isAuthenticated) return

You must be signed in to access this page.

+ + // Check if there is an Active Organization + if (!orgId) return

Set an Active Organization to access this page.

+ + // Check if the user has the `org:admin` Role + if (!has({ role: 'org:admin' })) return

You must be an admin to access this page.

+ + // Initialize the JS Backend SDK + // This varies depending on the SDK you're using + // https://clerk.com/docs/js-backend/getting-started/quickstart + const client = await clerkClient() + + // Use the `getOrganization()` method to get the Backend `Organization` object + const organization = await client.organizations.getOrganization({ organizationId: orgId }) + + // Check if Organization name matches (e.g. 'Acme Corp') + if (organization.name !== requiredOrgName) + return ( +

+ This page is only accessible in the {requiredOrgName} Organization. Switch + to the {requiredOrgName} Organization to access this page. +

+ ) + + return ( +

+ You are currently signed in as an admin in the{' '} + {organization.name} Organization. +

+ ) + } + ``` +
+ + + ```tsx {{ filename: 'app/protected/page.tsx' }} + 'use client' + import { OrganizationSwitcher, useAuth, useOrganization } from '@clerk/nextjs' + + export default function Page() { + // The `useAuth()` hook gives you access to properties like `isSignedIn` and `has()` + const { isSignedIn, has } = useAuth() + const { organization } = useOrganization() + const requiredOrgName = 'Acme Corp' + + // Check if the user is authenticated + if (!isSignedIn) return

You must be signed in to access this page.

+ + // Check if there is an Active Organization + if (!organization) return

Set an active organization to access this page.

+ + // Check if the user has the `org:admin` Role + if (!has({ role: 'org:admin' })) return

You must be an admin to access this page.

+ + // Check if Organization name matches (e.g. 'Acme Corp') + if (organization.name !== requiredOrgName) + return ( +

+ This page is only accessible in the {requiredOrgName} Organization. Switch + to the {requiredOrgName} Organization to access this page. +

+ ) + + return ( +

+ You are currently signed in as an admin in the{' '} + {organization.name} Organization. +

+ ) + } + ``` +
+
+ + Navigate to [`localhost:3000/protected`](localhost:3000/protected). You should see a green message confirming you are an admin in `Acme Corp`. Use the `` to switch Organizations or rename the Organization to show the red message. + + Learn more about protecting routes and checking Organization Roles in the [authorization guide](/docs/guides/organizations/control-access/roles-and-permissions). + + ## It's time to build your B2B SaaS! + + +
diff --git a/docs/guides/organizations/getting-started.nuxt.mdx b/docs/guides/organizations/getting-started.nuxt.mdx new file mode 100644 index 0000000000..84a1bea5fd --- /dev/null +++ b/docs/guides/organizations/getting-started.nuxt.mdx @@ -0,0 +1,242 @@ +--- +title: Get started with Organizations and Nuxt +description: Create and manage organizations in your Nuxt app in this guided tutorial. +sdk: nuxt +--- + + + +Organizations let you group users with Roles and Permissions, enabling you to build multi-tenant B2B apps like Slack (workspaces), Linear (teams), or Vercel (projects) where users can switch between different team contexts. This tutorial will demonstrate how to add Organizations, create and switch Organizations, and protect routes by Organization and Roles. + + + ## Add `` to your Nuxt app + + The `` component is the easiest way to let users create, switch between, and manage Organizations. It's recommended to place it in your app's header or navigation so it's always accessible to your users. For example: + + ```vue {{ filename: 'app/layouts/default.vue' }} + + ``` + + ## Access Organization data + + + + Use the [`useOrganization()`](/docs/nuxt/reference/composables/use-organization) hook to access information about the currently [Active Organization](!active-organization). Use the [`useAuth()`](/docs/nuxt/reference/composables/use-auth) composable to access authentication information about the current user, such as their Role in the Active Organization. + + ```vue {{ filename: 'app/pages/index.vue' }} + + + + ``` + + + + To access information about the currently [Active Organization](!active-organization) on the server-side, use `clerkClient()` to call the [`getOrganization()`](/docs/reference/backend/organization/get-organization) method, which returns the Backend [`Organization`](/docs/reference/backend/types/backend-organization) object. You'll need to pass an `orgId`, which you can access from the [`Auth`](/docs/reference/backend/types/auth-object) object. + + ```ts {{ filename: 'server/api/organization.ts' }} + import { clerkClient } from '@clerk/nuxt/server' + + export default defineEventHandler(async (event) => { + // Use `event.context.auth()` to access the `Auth` object + // https://clerk.com/docs/reference/backend/types/auth-object + const { isAuthenticated, orgId } = event.context.auth() + + // Check if the user is authenticated + if (!isAuthenticated) { + throw createError({ + statusCode: 401, + statusMessage: 'Unauthorized: No user ID provided', + }) + } + + // Check if there is an Active Organization + if (!orgId) { + throw createError({ + statusCode: 404, + statusMessage: 'Set an Active Organization to access this page.', + }) + } + + // Use the `getOrganization()` method to get the Backend `Organization` object + const organization = await clerkClient(event).organizations.getOrganization({ + organizationId: orgId, + }) + + return organization + }) + ``` + + + + ## Visit your app + + Run your project with the following command: + + ```npm + npm run dev + ``` + + Visit your app locally at [`localhost:3000`](http://localhost:3000). + + ### Enable organizations + + When prompted, select **Enable Organizations**. + + ### Create first user and Organization + + You must sign in to use Organizations. When prompted, select **Sign in to continue**. Then, authenticate to create your first user. + + Since you selected disabled Personal Accounts when you enabled Organizations, every user must be in at least one Organization. [Clerk will prompt you](!choose-organization) to create an Organization for your user. + + ## Create and switch Organizations + + At this point, Clerk should have redirected you to a page with the [``](/docs/reference/components/organization/organization-switcher) component. This component allows you to create, switch between, and manage Organizations. + + 1. Select the `` component, then **Create an organization**. + 1. Enter `Acme Corp` as the Organization name. + 1. Invite users to your Organization and select their Role. + + ## Protect routes by Organization and Roles + + You can protect content and even entire routes based on Organization membership, Roles, and Permissions by performing [authorization checks](!authorization-check). + + In the following example, the page is protected from unauthenticated users, users that don't have the `org:admin` Role, and users that are not in the `Acme Corp` Organization. It uses the [`has()`](/docs/reference/backend/types/auth-object#has) helper to perform the authorization check for the `org:admin` Role. + + + + ```vue {{ filename: 'app/pages/index.vue', collapsible: true }} + + + + ``` + + + + ```ts {{ filename: 'server/api/organization.ts' }} + import { clerkClient } from '@clerk/nuxt/server' + + export default defineEventHandler(async (event) => { + const { isAuthenticated, orgId } = event.context.auth() + const requiredOrgName = 'Acme Corp' + + // Check if the user is authenticated + if (!isAuthenticated) { + throw createError({ + statusCode: 401, + statusMessage: 'Unauthorized: No user ID provided', + }) + } + + // Check if there is an Active Organization + if (!orgId) { + throw createError({ + statusCode: 404, + statusMessage: 'Set an Active Organization to access this page.', + }) + } + + // Use the `getOrganization()` method to get the Backend `Organization` object + const organization = await clerkClient(event).organizations.getOrganization({ + organizationId: orgId, + }) + + // Check if Organization name matches (e.g., "Acme Corp") + if (organization.name !== requiredOrgName) { + throw createError({ + statusCode: 403, + statusMessage: `This route is only accessible in the ${requiredOrgName} Organization.`, + }) + } + + return { + organization, + } + }) + ``` + + + + Navigate to [`localhost:3000/protected`](localhost:3000/protected). You should see a green message confirming you are an admin in `Acme Corp`. Use the `` to switch Organizations or rename the Organization to show the red message. + + Learn more about protecting routes and checking Organization Roles in the [authorization guide](/docs/guides/organizations/control-access/roles-and-permissions). + + ## It's time to build your B2B SaaS! + + + diff --git a/docs/guides/organizations/getting-started.react-router.mdx b/docs/guides/organizations/getting-started.react-router.mdx new file mode 100644 index 0000000000..4c2b5cea9c --- /dev/null +++ b/docs/guides/organizations/getting-started.react-router.mdx @@ -0,0 +1,400 @@ +--- +title: Get started with Organizations and React Router +description: Create and manage organizations in your React Router app in this guided tutorial. +sdk: react-router +--- + + + +Organizations let you group users with Roles and Permissions, enabling you to build multi-tenant B2B apps like Slack (workspaces), Linear (teams), or Vercel (projects) where users can switch between different team contexts. This tutorial will demonstrate how to add Organizations, create and switch Organizations, and protect routes by Organization and Roles. + + + ## Add `` to your app + + The `` component is the easiest way to let users create, switch between, and manage Organizations. It's recommended to place it in your app's header or navigation so it's always accessible to your users. For example: + + ```tsx {{ filename: 'app/root.tsx', fold: [[11, 50], [71, 97]], collapsible: true }} + import { + ClerkProvider, + SignedIn, + SignedOut, + UserButton, + SignInButton, + + OrganizationSwitcher, + } from '@clerk/react-router' + import { isRouteErrorResponse, Links, Meta, Outlet, Scripts, ScrollRestoration } from 'react-router' + import { clerkMiddleware, rootAuthLoader } from '@clerk/react-router/server' + + import type { Route } from './+types/root' + import stylesheet from './app.css?url' + + export const middleware: Route.MiddlewareFunction[] = [clerkMiddleware()] + + export const loader = (args: Route.LoaderArgs) => rootAuthLoader(args) + + export const links: Route.LinksFunction = () => [ + { rel: 'preconnect', href: 'https://fonts.googleapis.com' }, + { + rel: 'preconnect', + href: 'https://fonts.gstatic.com', + crossOrigin: 'anonymous', + }, + { + rel: 'stylesheet', + href: 'https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap', + }, + { rel: 'stylesheet', href: stylesheet }, + ] + + export function Layout({ children }: { children: React.ReactNode }) { + return ( + + + + + + + + + {children} + + + + + ) + } + + // Pull in the `loaderData` from the `rootAuthLoader()` function + export default function App({ loaderData }: Route.ComponentProps) { + return ( + // Pass the `loaderData` to the `` component + +
+ + + {/* Show the sign-in button when the user is signed out */} + + + + {/* Show the user button when the user is signed in */} + + + +
+ +
+ ) + } + + export function ErrorBoundary({ error }: Route.ErrorBoundaryProps) { + let message = 'Oops!' + let details = 'An unexpected error occurred.' + let stack: string | undefined + + if (isRouteErrorResponse(error)) { + message = error.status === 404 ? '404' : 'Error' + details = + error.status === 404 ? 'The requested page could not be found.' : error.statusText || details + } else if (import.meta.env.DEV && error && error instanceof Error) { + details = error.message + stack = error.stack + } + + return ( +
+

{message}

+

{details}

+ {stack && ( +
+              {stack}
+            
+ )} +
+ ) + } + ``` + + ## Access Organization data + + + + Use the [`useOrganization()`](/docs/reference/hooks/use-organization) hook to access information about the currently [Active Organization](!active-organization). Use the [`useOrganizationList()`](/docs/reference/hooks/use-organization-list) hook to access information about the current user's Organization memberships. + + ```tsx {{ filename: 'src/welcome/welcome.tsx' }} + import { useOrganization, useOrganizationList } from '@clerk/react-router' + + export function Welcome() { + const { organization } = useOrganization() + const { userMemberships } = useOrganizationList({ + userMemberships: true, + }) + + return ( +
+

+ Welcome to the {organization?.name} organization +

+

+ Your role in this organization:{' '} + + { + userMemberships?.data?.find( + (membership) => membership.organization.id === organization?.id, + )?.role + } + +

+
+ ) + } + ``` +
+ + + To access information about the currently [Active Organization](!active-organization) on the server-side, use [`clerkClient()`](/docs/reference/react-router/overview#clerk-client) to call the [`getOrganization()`](/docs/reference/backend/organization/get-organization) method, which returns the Backend [`Organization`](/docs/reference/backend/types/backend-organization) object. You'll need to pass an `orgId`, which you can access from the [`Auth`](/docs/reference/backend/types/auth-object) object. + + In the following example, the loader runs on the server before the `` component renders. This allows you to perform authentication checks before sending any data to the client, so all necessary data is available when the component is rendered. + + ```tsx {{ filename: 'app/routes/home.tsx', collapsible: true }} + import { redirect } from 'react-router' + import { clerkClient, getAuth } from '@clerk/react-router/server' + import type { Organization } from '@clerk/backend' + import type { Route } from './+types/home' + import { Welcome } from '../welcome/welcome' + + export function meta({}: Route.MetaArgs) { + return [ + { title: 'New React Router App' }, + { name: 'description', content: 'Welcome to React Router!' }, + ] + } + + export async function loader(args: Route.LoaderArgs) { + // Use the `getAuth()` helper to access the `Auth` object + // https://clerk.com/docs/reference/backend/types/auth-object + const { isAuthenticated, orgId, orgRole } = await getAuth(args) + + // Check if the user is authenticated + if (!isAuthenticated) { + return redirect('/sign-in?redirect_url=' + args.request.url) + } + + // Check if there is an Active Organization + if (!orgId) { + return { organization: null, orgRole: null, hasOrganization: false } + } + + // Initialize the JS Backend SDK + // This varies depending on the SDK you're using + // https://clerk.com/docs/js-backend/getting-started/quickstart + // Use the `getOrganization()` method to get the Backend `Organization` object + const organization = await clerkClient(args).organizations.getOrganization({ + organizationId: orgId, + }) + + return { organization, orgRole } + } + + export default function Home({ loaderData }: Route.ComponentProps) { + return ( + + ) + } + ``` + + Update the `` component to display information about the user's Active Organization. + + ```tsx {{ filename: 'app/welcome/welcome.tsx' }} + type LoaderData = Awaited> + + interface WelcomeProps { + loaderData: LoaderData + } + + export function Welcome({ loaderData }: WelcomeProps) { + if (!loaderData || loaderData instanceof Response) return null + + return ( +
+

Welcome to the {loaderData.organization?.name} Organization

+

Your role in this organization: {loaderData.orgRole}

+
+ ) + } + ``` +
+
+ + ## Visit your app + + Run your project with the following command: + + ```npm + npm run dev + ``` + + Visit your app locally at [`localhost:5173`](http://localhost:5173). + + ### Enable Organizations + + When prompted, select **Enable Organizations**. + + ### Create first user and Organization + + You must sign in to use Organizations. When prompted, select **Sign in to continue**. Then, authenticate to create your first user. + + Since you selected disabled personal accounts when you enabled Organizations, every user must be in at least one Organization. [Clerk will prompt you](!choose-organization) to create an Organization for your user. + + ## Create and switch Organizations + + At this point, Clerk should have redirected you to a page with the [``](/docs/reference/components/organization/organization-switcher) component. This component allows you to create, switch between, and manage Organizations. + + 1. Select the `` component, then **Create an organization**. + 1. Enter `Acme Corp` as the Organization name. + 1. Invite users to your Organization and select their Role. + + ## Protect routes by Organization and Roles + + You can protect content and even entire routes based on Organization membership, Roles, and Permissions by performing [authorization checks](!authorization-check). + + In the following example, the page is protected from unauthenticated users, users that don't have the `org:admin` Role, and users that are not in the `Acme Corp` Organization. It uses the [`has()`](/docs/reference/backend/types/auth-object#has) helper to perform the authorization check for the `org:admin` Role. + + + + ```tsx {{ filename: 'app/routes/protected.tsx', collapsible: true }} + import type { Route } from './+types/protected' + import { useAuth, useOrganization } from '@clerk/react-router' + + export function meta({}: Route.MetaArgs) { + return [ + { title: 'Protected Page' }, + { name: 'description', content: 'A protected page requiring admin access' }, + ] + } + + export default function Protected() { + const { isSignedIn, has } = useAuth() + const { organization } = useOrganization() + + // Check if the user is authenticated + if (!isSignedIn) return

You must be signed in to access this page.

+ + // Check if there is an Active Organization + if (!organization) return

Set an Active Organization to access this page.

+ + // Check if the user has the `org:admin` Role + if (!has({ role: 'org:admin' })) return

You must be an admin to access this page.

+ + // Check if Organization name matches (e.g., "Acme Corp") + const requiredOrgName = 'Acme Corp' + if (organization.name !== requiredOrgName) + return ( +

+ This page is only accessible in the {requiredOrgName} Organization. Switch + to the {requiredOrgName} Organization to access this page. +

+ ) + + return ( +

+ You are currently signed in as an admin in the{' '} + {organization.name} Organization. +

+ ) + } + ``` +
+ + + ```tsx {{ filename: 'app/routes/protected.tsx', collapsible: true }} + import { clerkClient, getAuth } from '@clerk/react-router/server' + import { redirect } from 'react-router' + import type { Route } from '../+types/protected' + + export function meta({}: Route.MetaArgs) { + return [ + { title: 'Protected Page' }, + { name: 'description', content: 'A protected page requiring admin access' }, + ] + } + + export async function loader(args: Route.LoaderArgs) { + // Use the `getAuth()` helper to access the `Auth` object + // https://clerk.com/docs/reference/backend/types/auth-object + const { isAuthenticated, orgId, has } = await getAuth(args) + + // Check if the user is authenticated + if (!isAuthenticated) { + return redirect('/sign-in?redirect_url=' + args.request.url) + } + + // Check if there is an Active Organization + if (!orgId) return { error: 'Set an Active Organization to access this page.' } + + // Check if the user has the `org:admin` Role + if (!has({ role: 'org:admin' })) return { error: 'You must be an admin to access this page.' } + + // Initialize the JS Backend SDK + // This varies depending on the SDK you're using + // https://clerk.com/docs/js-backend/getting-started/quickstart + // Use the `getOrganization()` method to get the Backend `Organization` object + const organization = await clerkClient(args).organizations.getOrganization({ + organizationId: orgId, + }) + + // Check if Organization name matches (e.g. 'Acme Corp') + const requiredOrgName = 'Acme Corp' + if (organization.name !== requiredOrgName) + return { + error: `This page is only accessible in the ${requiredOrgName} Organization. Switch to the ${requiredOrgName} Organization to access this page.`, + } + + return { organization } + } + + export default function Protected({ loaderData }: Route.ComponentProps) { + return ( +

+ You are currently signed in as an admin in the{' '} + {loaderData?.organization?.name} Organization. +

+ ) + } + ``` +
+
+ + Update your routes configuration to show the `` component when you navigate to `/protected`. + + ```tsx {{ filename: 'app/routes.ts', mark: [5] }} + import { type RouteConfig, index, route } from '@react-router/dev/routes' + + export default [ + index('routes/home.tsx'), + route('protected', 'routes/protected.tsx'), + ] satisfies RouteConfig + ``` + + Navigate to [`localhost:5173/protected`](localhost:5173/protected). You should see a green message confirming you are an admin in `Acme Corp`. Use the `` to switch Organizations or rename the Organization to show the red message. + + Learn more about protecting routes and checking Organization Roles in the [authorization guide](/docs/guides/organizations/control-access/roles-and-permissions). + + ## It's time to build your B2B SaaS! + + +
diff --git a/docs/guides/organizations/getting-started.react.mdx b/docs/guides/organizations/getting-started.react.mdx new file mode 100644 index 0000000000..2ae7424115 --- /dev/null +++ b/docs/guides/organizations/getting-started.react.mdx @@ -0,0 +1,253 @@ +--- +title: Get started with Organizations and React +description: Create and manage organizations in your React app in this guided tutorial. +sdk: react +--- + + + +Organizations let you group users with roles and permissions, enabling you to build multi-tenant B2B apps like Slack (workspaces), Linear (teams), or Vercel (projects) where users can switch between different team contexts. This tutorial will demonstrate how to add Organizations, create and switch Organizations, and protect routes by Organization and Roles. + + + ## Add `` to your app + + The `` component is the easiest way to let users create, switch between, and manage Organizations. It's recommended to place it in your app's header or navigation so it's always accessible to your users. For example: + + ```tsx {{ filename: 'src/App.tsx' }} + import './App.css' + import { + SignedIn, + SignedOut, + SignInButton, + UserButton, + + OrganizationSwitcher, + } from '@clerk/clerk-react' + + function App() { + return ( + <> +
+ + + + + + + + +
+ + ) + } + + export default App + ``` + + ## Access Organization data + + Use the [`useOrganization()`](/docs/reference/hooks/use-organization) hook to access information about the currently [Active Organization](!active-organization). Use the [`useOrganizationList()`](/docs/reference/hooks/use-organization-list) hook to access information about the current user's Organization memberships. + + ```tsx {{ filename: 'src/App.tsx' }} + import './App.css' + import { + SignedIn, + SignedOut, + SignInButton, + UserButton, + OrganizationSwitcher, + useOrganization, + useOrganizationList, + } from '@clerk/clerk-react' + + function App() { + const { organization } = useOrganization() + const { userMemberships } = useOrganizationList({ + userMemberships: true, + }) + + return ( + <> +
+ + + + + + + +
+
+ +
+

+ Welcome to the {organization?.name} organization +

+

+ Your role in this organization:{' '} + + { + userMemberships?.data?.find( + (membership) => membership.organization.id === organization?.id, + )?.role + } + +

+
+
+
+ + ) + } + + export default App + ``` + + ## Visit your app + + Run your project with the following command: + + ```npm + npm run dev + ``` + + Visit your app locally at [`localhost:5173`](http://localhost:5173). + + ### Enable Organizations + + When prompted, select **Enable Organizations**. + + ### Create first user and Organization + + You must sign in to use Organizations. When prompted, select **Sign in to continue**. Then, authenticate to create your first user. + + Since you selected disabled Personal Accounts when you enabled Organizations, every user must be in at least one Organization. [Clerk will prompt you](!choose-organization) to create an Organization for your user. + + ## Create and switch Organizations + + At this point, Clerk should have redirected you to a page with the [``](/docs/reference/components/organization/organization-switcher) component. This component allows you to create, switch between, and manage Organizations. + + 1. Select the `` component, then **Create an organization**. + 1. Enter `Acme Corp` as the Organization name. + 1. Invite users to your Organization and select their Role. + + ## Protect routes by Organization and Roles + + You can protect content and even entire routes based on Organization membership, Roles, and Permissions by performing [authorization checks](!authorization-check). + + In the following example, the page is protected from unauthenticated users, users that don't have the `org:admin` Role, and users that are not in the `Acme Corp` Organization. It uses the [`has()`](/docs/reference/backend/types/auth-object#has) helper to perform the authorization check for the `org:admin` Role. + + ```tsx {{ filename: 'src/Protected.tsx', collapsible: true }} + import { useAuth, useOrganization } from '@clerk/clerk-react' + + export default function Protected() { + const { isSignedIn, has } = useAuth() + const { organization } = useOrganization() + + // Check if the user is authenticated + if (!isSignedIn) return

You must be signed in to access this page.

+ + // Check if there is an Active Organization + if (!organization)

Set an Active Organization to access this page.

+ + // Check if the user has the `org:admin` Role + if (!has({ role: 'org:admin' })) return

You must be an admin to access this page.

+ + // Check if Organization name matches (e.g. 'Acme Corp') + const requiredOrgName = 'Acme Corp' + if (organization.name !== requiredOrgName) { + return ( + <> +

+ This page is only accessible in the {requiredOrgName} Organization. + Switch to the {requiredOrgName} Organization to access this page. +

+ + ) + } + + return ( +

+ You are currently signed in as an admin in the{' '} + {organization.name} Organization. +

+ ) + } + ``` + + Update your main `` component to show the `` component when you navigate to `/protected`. + + ```tsx {{ filename: 'src/App.tsx', mark: [[31, 33]], collapsible: true }} + import './App.css' + import { + SignedIn, + SignedOut, + SignInButton, + UserButton, + OrganizationSwitcher, + useOrganization, + useOrganizationList, + } from '@clerk/clerk-react' + import Protected from './Protected' + + function App() { + const { organization } = useOrganization() + const { userMemberships } = useOrganizationList({ + userMemberships: true, + }) + + return ( + <> +
+ + + + + + + +
+
+ {window.location.pathname === '/protected' ? ( + + ) : ( + +
+

+ Welcome to the {organization?.name} Organization +

+

+ Your role in this Organization:{' '} + + { + userMemberships?.data?.find( + (membership) => membership.organization.id === organization?.id, + )?.role + } + +

+
+
+ )} +
+ + ) + } + + export default App + ``` + + Navigate to [`localhost:5173/protected`](localhost:5173/protected). You should see a green message confirming you are an admin in `Acme Corp`. Use the `` to switch Organizations or rename the Organization to show the red message. + + Learn more about protecting routes and checking Organization Roles in the [authorization guide](/docs/guides/organizations/control-access/roles-and-permissions). + + ## It's time to build your B2B SaaS! + + +
diff --git a/docs/guides/organizations/metadata.mdx b/docs/guides/organizations/metadata.mdx index 49f1cfd541..ff384bb62b 100644 --- a/docs/guides/organizations/metadata.mdx +++ b/docs/guides/organizations/metadata.mdx @@ -5,33 +5,52 @@ metadata: title: Custom metadata for B2B authentication flows --- -Organization metadata allows you to store information about an organization that is not part of the standard fields, such as custom attributes that are specific to your application. +Organization metadata lets you store custom information about an Organization that is not part of the standard fields, such as custom attributes that are specific to your application. This is useful for advanced user segmentation, analytics, or storing application-specific data like subscription tier, department, or region. -There are two types of metadata: **public** and **private**. +Metadata is stored on the [`Organization`](/docs/reference/javascript/organization) and [`OrganizationMembership`](/docs/reference/javascript/types/organization-membership) objects. -- Both **public** and **private** metadata are set and can be accessed from the [Backend API](/docs/reference/backend-api){{ target: '_blank' }}. -- Only **public** metadata can be accessed from the [Frontend API](/docs/reference/frontend-api/){{ target: '_blank' }}. +## Types of metadata -Both the `Organization` and `Organization Membership` objects have the metadata fields: `publicMetadata` and `privateMetadata`. +There are two types of Organization metadata: **public** and **private**. + +| Metadata | Frontend API | Backend API | +| - | - | - | +| Public | Read access | Read & write access | +| Private | No read or write access | Read & write access | + +Both the [`Organization`](/docs/reference/javascript/organization) and [`OrganizationMembership`](/docs/reference/javascript/types/organization-membership) objects have the metadata fields: `publicMetadata` and `privateMetadata`. - Use the `publicMetadata` property if you need to set some metadata from your backend and have them displayed as read-only on the frontend. - Use the `privateMetadata` property if the custom attributes contain sensitive information that should not be displayed on the frontend. -## Set organization metadata +## Set Organization metadata + +You can set Organization metadata in the [Clerk Dashboard](https://dashboard.clerk.com/~/organizations) or using Clerk's Backend API. See the [`updateOrganizationMetadata()`](/docs/reference/backend/organization/update-organization-metadata) and [`updateOrganizationMembershipMetadata()`](/docs/reference/backend/organization/update-organization-membership-metadata) methods for more information. + +## Access public metadata + +To access public metadata on the frontend, it's available on the [`Organization`](/docs/reference/javascript/organization) object, which can be accessed using the [`useOrganization()`](/docs/reference/hooks/use-organization) hook. + +To access public metadata on the backend, it's available on the [Backend `Organization`](/docs/reference/backend/types/backend-organization) object which can be accessed using the [`getOrganization()`](/docs/reference/backend/organization/get-organization) method. This method will return the `Organization` object which contains the public metadata. However, this method is subject to [rate limits](/docs/guides/how-clerk-works/system-limits#backend-api-requests), so _if you are accessing the metadata frequently_, it's recommended to [attach it to the user's session token](#metadata-in-the-session-token). + +## Metadata in the session token + +Retrieving metadata from the `Organization` or `OrganizationMembership` objects on the server-side requires making an API request to Clerk's Backend API, which is slower and is subject to [rate limits](/docs/guides/how-clerk-works/system-limits#backend-api-requests). You can store it in the user's session token, which doesn't require making an API request as it's available on the user's authentication context. **However, there is a size limitation to keep in mind.** Clerk stores the session token in a cookie, and most browsers cap cookie size at [**4KB**](https://datatracker.ietf.org/doc/html/rfc2109#section-6.3). After accounting for the size of Clerk's default claims, the cookie can support **up to 1.2KB** of custom claims. **Exceeding this limit will cause the cookie to not be set, which will break your app as Clerk depends on cookies to work properly.** -There are two ways to set organization metadata: +If you need to store more than 1.2KB of metadata, you should [store the extra data in your own database](/docs/guides/development/webhooks/syncing#storing-extra-user-data) instead. If this isn't an option, you can [move particularly large claims out of the token](/docs/guides/sessions/session-tokens#example) and fetch them using a separate API call from your backend, but this approach brings back the issue of making an API request to Clerk's Backend API, which is slower and is subject to rate limits. -- In the Clerk Dashboard -- Using the [JS Backend SDK](/docs/js-backend/getting-started/quickstart) +Another limitation of storing metadata in the session token is that when you modify metadata server-side, the changes won't appear in the session token until the next refresh. To avoid race conditions, either [force a JWT refresh](/docs/guides/sessions/force-token-refresh) after metadata changes or handle the delay in your application logic. -### In the Clerk Dashboard +If you've considered the limitations, and you still want to store metadata in the session token: -1. In the Clerk Dashboard, navigate to the [**Organizations**](https://dashboard.clerk.com/~/organizations) page. -1. Select the organization you want to update. -1. In the **Organization metadata** section, select **Edit** next to the metadata you want to update. +1. In the Clerk Dashboard, navigate to the [**Sessions**](https://dashboard.clerk.com/~/sessions) page. +1. Under **Customize session token**, in the **Claims** editor, you can add any claim to your session token that you need and select **Save**. To avoid exceeding the session token's 1.2KB limit, it's not recommended to add the entire `organization.public_metadata` or `organization_membership.public_metadata` object. Instead, add individual fields as claims, like `organization.public_metadata.birthday`. When doing this, it's recommended to leave particularly large claims out of the token to avoid exceeding the session token's size limit. See the [example](/docs/guides/sessions/session-tokens#example) for more information. -### Using the JS Backend SDK +## Next steps -To ease the flow of setting metadata, Clerk provides the [`updateOrganizationMetadata()`](/docs/reference/backend/organization/update-organization-metadata) and [`updateOrganizationMembershipMetadata()`](/docs/reference/backend/organization/update-organization-membership-metadata) methods from the [JS Backend](/docs/js-backend/getting-started/quickstart), which is a wrapper around the [Backend API](/docs/reference/backend-api){{ target: '_blank' }}. +Now that you understand Organization metadata, you can: - +- [Add metadata to invitations](/docs/guides/organizations/add-members/invitations#invitation-metadata) to track invitation sources or assign attributes +- [Create and manage Organizations](/docs/guides/organizations/create-and-manage) to see metadata in action +- [Control access based on Roles and Permissions](/docs/guides/secure/authorization-checks) +- [Use Organization slugs in URLs](/docs/guides/organizations/org-slugs-in-urls) for tenant-specific routing diff --git a/docs/guides/organizations/org-slugs-in-urls.mdx b/docs/guides/organizations/org-slugs-in-urls.mdx index 57b38810f9..0f7abf2d43 100644 --- a/docs/guides/organizations/org-slugs-in-urls.mdx +++ b/docs/guides/organizations/org-slugs-in-urls.mdx @@ -1,8 +1,8 @@ --- -title: Use organization slugs in URLs -description: Learn how to use organization slugs in your application URLs to build tenant-specific authentication flows. Enable seamless switching between active orgs (one-to-many or many-to-many) with Clerk's secure and scalable multi-tenant authentication suite. +title: Use Organization slugs in URLs +description: Learn how to use Organization slugs in your application URLs to build tenant-specific authentication flows. Enable seamless switching between active Organizations (one-to-many or many-to-many) with Clerk's secure and scalable multi-tenant authentication suite. metadata: - title: Use organization slugs in URLs for tenant-specific auth flows + title: Use Organization slugs in URLs for tenant-specific auth flows --- -Organization slugs are human-readable URL identifiers that help users reference which organization they're working in. A common pattern for organization-scoped areas in an application is to include the organization slug in the URL path. +Organization slugs are human-readable URL identifiers (like `acme-corp` or `marketing-team`) that help users reference which Organization they're working in. A common pattern for Organization-scoped areas in an application is to include the Organization slug in the URL path, making links sharable and providing clear context about which tenant the page belongs to. -For example, a B2B application named "Petstore" has two customer organizations: **Acmecorp** and **Widgetco**. Each organization uses its name as a slug in the URL: +For example, a B2B application named "Petstore" has two customer Organizations: **Acmecorp** and **Widgetco**. Each Organization uses its name as a slug in the URL: - **Acmecorp**: `https://petstore.example.com/orgs/`**`acmecorp`**`/dashboard` - **Widgetco**: `https://petstore.example.com/orgs/`**`widgetco`**`/dashboard` -Alternatively, [organization IDs](/docs/reference/javascript/organization#properties) can be used to identify organizations in URLs: +Alternatively, [Organization IDs](/docs/reference/javascript/organization#properties) can be used to identify Organizations in URLs: - **Acmecorp**: `https://petstore.example.com/orgs/`**`org_1a2b3c4d5e6f7g8e`**`/dashboard` - **Widgetco**: `https://petstore.example.com/orgs/`**`org_1a2b3c4d5e6f7g8f`**`/dashboard` -### When to use organization slugs +### When to use Organization slugs -This feature is intended for apps that **require** organization slugs in URLs. **Adding slugs to URLs isn't recommended unless necessary.** +This feature is intended for apps that **require** Organization slugs in URLs. **We don't recommend adding slugs to URLs unless necessary.** -Use organization slugs if: +Use Organization slugs if: -- Users frequently share links for public-facing content (e.g., documentation, marketing materials, and third-party blogs) -- Users regularly switch between multiple organizations -- Organization-specific URLs provide meaningful context +- Users frequently share links for public-facing content (e.g., documentation, marketing materials, and third-party blogs). +- Users regularly switch between multiple Organizations. +- Organization-specific URLs provide meaningful context. -**Don't** use organization slugs if: +**Don't** use Organization slugs if: -- Most users belong to only one organization -- You want to keep URLs simple and consistent -- You're primarily using the Clerk session for organization context +- Most users belong to only one Organization. +- You want to keep URLs simple and consistent. +- You're primarily using the Clerk session for Organization context. -This guide shows you how to add organization slugs to your app's URLs, configure Clerk components to handle slug-based navigation, and access organization data based on the URL slug at runtime. +This guide shows you how to add Organization slugs to your app's URLs, configure Clerk components to handle slug-based navigation, and access Organization data based on the URL slug at runtime. ## Configure `` and `` - The [``](/docs/reference/components/organization/organization-switcher) and [``](/docs/reference/components/organization/organization-list) components provide a robust set of options to manage organization slugs and IDs in your application's URLs. + The [``](/docs/reference/components/organization/organization-switcher) and [``](/docs/reference/components/organization/organization-list) components provide a robust set of options to manage Organization slugs and IDs in your application's URLs. Set the following properties to configure the components to handle slug-based navigation: - - Set `hideSlug` to `false` to allow users to customize the organization's URL slug when creating an organization. - - Set `afterCreateOrganizationUrl` to `/orgs/:slug` to navigate the user to the organization's slug after creating an organization. - - Set `afterSelectOrganizationUrl` to `/orgs/:slug` to navigate the user to the organization's slug after selecting it. + - Set `hideSlug` to `false` to allow users to customize the Organization's URL slug when creating an Organization. + - Set `afterCreateOrganizationUrl` to `/orgs/:slug` to navigate the user to the Organization's slug after creating an Organization. + - Set `afterSelectOrganizationUrl` to `/orgs/:slug` to navigate the user to the Organization's slug after selecting it. - For example, if the organization has the slug `acmecorp`, when a user creates or selects that organization using either component, they'll be redirected to `/orgs/acmecorp`. + For example, if the Organization has the slug `acmecorp`, when a user creates or selects that Organization using either component, they'll be redirected to `/orgs/acmecorp`. ", ""]}> @@ -113,14 +113,14 @@ This guide shows you how to add organization slugs to your app's URLs, configure > [!TIP] > If your app doesn't use `clerkMiddleware()`, or you prefer to manually set the [Active Organization](!active-organization), use the [`setActive()`](/docs/reference/javascript/clerk) method to control the Active Organization on the client-side. - With [`clerkMiddleware()`](/docs/reference/nextjs/clerk-middleware), you can use the [`organizationSyncOptions`](/docs/reference/nextjs/clerk-middleware#organization-sync-options) property to declare URL patterns that determine whether a specific organization should be activated. + With [`clerkMiddleware()`](/docs/reference/nextjs/clerk-middleware), you can use the [`organizationSyncOptions`](/docs/reference/nextjs/clerk-middleware#organization-sync-options) property to declare URL patterns that determine whether a specific Organization should be activated. - If the middleware detects one of these patterns in the URL and finds that a different organization is active in the session, it'll attempt to set the specified organization as the active one. + If the middleware detects one of these patterns in the URL and finds that a different Organization is active in the session, it'll attempt to set the specified Organization as the active one. - In the following example, two `organizationPatterns` are defined: one for the root (e.g., `/orgs/acmecorp`) and one as the wildcard matcher `(.*)` to match `/orgs/acmecorp/any/other/resource`. This configuration ensures that the path `/orgs/:slug` with any optional trailing path segments will set the organization indicated by the slug as the active one. + In the following example, two `organizationPatterns` are defined: one for the root (e.g., `/orgs/acmecorp`) and one as the wildcard matcher `(.*)` to match `/orgs/acmecorp/any/other/resource`. This configuration ensures that the path `/orgs/:slug` with any optional trailing path segments will set the Organization indicated by the slug as the active one. > [!WARNING] - > If no organization with the specified slug exists, or if the user isn't a member of the organization, then `clerkMiddleware()` **won't** modify the Active Organization. Instead, it will leave the previously Active Organization unchanged on the Clerk session. + > If no Organization with the specified slug exists, or if the user isn't a member of the Organization, then `clerkMiddleware()` **won't** modify the Active Organization. Instead, it will leave the previously Active Organization unchanged on the Clerk session. ```tsx {{ filename: 'proxy.ts', mark: [[7, 13]] }} import { clerkMiddleware } from '@clerk/nextjs/server' @@ -151,17 +151,17 @@ This guide shows you how to add organization slugs to your app's URLs, configure ### Handle failed activation - Now that `clerkMiddleware()` is configured to activate organizations, you can build an organization-specific page while handling cases where the organization can't be activated. + Now that `clerkMiddleware()` is configured to activate Organizations, you can build an Organization-specific page while handling cases where the Organization can't be activated. - Failed activation occurs if no organization with the specified slug exists, or if the given user isn't a member of the organization. When this happens, the middleware won't change the Active Organization, leaving the previously active one unchanged. + Failed activation occurs if no Organization with the specified slug exists, or if the given user isn't a member of the Organization. When this happens, the middleware won't change the Active Organization, leaving the previously active one unchanged. - For troubleshooting, a message will also be logged on the server: + For troubleshooting, Clerk will also log a message on the server: - > Clerk: Organization activation handshake loop detected. This is likely due to an invalid organization ID or slug. Skipping organization activation. + > Clerk: Organization activation handshake loop detected. This is likely due to an invalid Organization ID or slug. Skipping Organization activation. - It's ultimately the responsibility of the page to ensure that it renders the appropriate content for a given URL, and to handle the case where the expected organization **isn't** active. + It's ultimately the responsibility of the page to ensure that it renders the appropriate content for a given URL, and to handle the case where the expected Organization **isn't** active. - In the following example, the organization slug is detected as a Next.js [Dynamic Route](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes) param and passed as a parameter to the page. If the slug doesn't match the Active Organization slug, an error message is rendered and the [``](/docs/reference/components/organization/organization-list) component allows the user to select a valid organization. + In the following example, the Organization slug is detected as a Next.js [Dynamic Route](https://nextjs.org/docs/pages/building-your-application/routing/dynamic-routes) param and passed as a parameter to the page. If the slug doesn't match the Active Organization slug, an error message is rendered and the [``](/docs/reference/components/organization/organization-list) component allows the user to select a valid Organization. ```tsx {{ filename: 'app/orgs/[slug]/page.tsx' }} import { auth } from '@clerk/nextjs/server' @@ -171,13 +171,13 @@ This guide shows you how to add organization slugs to your app's URLs, configure const { orgSlug } = await auth() const { slug } = await params - // Check if the organization slug from the URL params doesn't match - // the Active Organization slug from the user's session. - // If they don't match, show an error message and the list of valid organizations. + // Check if the org slug from the URL params doesn't match + // the active org slug from the user's session. + // If they don't match, show an error message and the list of valid Organizations. if (slug != orgSlug) { return ( <> -

Sorry, organization {slug} is not valid.

+

Sorry, Organization {slug} is not valid.

Welcome to organization {orgSlug} + return
Welcome to Organization {orgSlug}
} ``` - ## Render organization-specific content + ## Render Organization-specific content - Use the following tabs to learn how to access organization information on the server-side and client-side. + Use the following tabs to learn how to access Organization information on the server-side and client-side. - To get organization information on the server-side, access the [`Auth`](/docs/reference/backend/types/auth-object) object which includes the active org's `orgId` and `orgSlug` and the current user's `orgRole` and `orgPermissions`. To access _additional_ organization information server-side, like the organization name, you can store the additional information in the user's session token. To [customize the session token](/docs/guides/sessions/customize-session-tokens), do the following: + To get Organization information on the server-side, access the [`Auth`](/docs/reference/backend/types/auth-object) object which includes the active org's `orgId` and `orgSlug` and the current user's `orgRole` and `orgPermissions`. To access _additional_ Organization information server-side, like the Organization name, you can store the additional information in the user's session token. To [customize the session token](/docs/guides/sessions/customize-session-tokens), do the following: 1. In the Clerk Dashboard, navigate to the [**Sessions**](https://dashboard.clerk.com/~/sessions) page. 1. Under **Customize session token**, in the **Claims** editor, add any claim you need to your session token. For this guide, add the following claim: @@ -219,13 +219,13 @@ This guide shows you how to add organization slugs to your app's URLs, configure const { orgSlug, sessionClaims } = await auth() const { slug } = await params - // Check if the organization slug from the URL params doesn't match - // the Active Organization slug from the user's session. - // If they don't match, show an error message and the list of valid organizations. + // Check if the org slug from the URL params doesn't match + // the active org slug from the user's session. + // If they don't match, show an error message and the list of valid Organizations. if (slug != orgSlug) { return ( <> -

Sorry, organization {slug} is not valid.

+

Sorry, Organization {slug} is not valid.

{orgId && `Welcome to organization ${orgId}`} @@ -244,7 +244,7 @@ This guide shows you how to add organization slugs to your app's URLs, configure
- To get organization information on the client-side, use the [`useOrganization()`](/docs/reference/hooks/use-organization) hook to access the [`organization`](/docs/reference/javascript/organization) object. + To get Organization information on the client-side, use the [`useOrganization()`](/docs/reference/hooks/use-organization) hook to access the [`organization`](/docs/reference/javascript/organization) object. ```tsx {{ filename: 'app/orgs/[slug]/page.tsx', mark: [[27, 28]] }} 'use client' @@ -252,16 +252,16 @@ This guide shows you how to add organization slugs to your app's URLs, configure import { OrganizationList, useOrganization } from '@clerk/nextjs' export default function Home({ params }: { params: { slug: string } }) { - // Use `useOrganization()` to access the currently Active Organization's `Organization` object + // Use `useOrganization()` to access the currently active org's `Organization` object const { organization } = useOrganization() - // Check if the organization slug from the URL params doesn't match - // the Active Organization slug from the user's session. - // If they don't match, show an error message and the list of valid organizations. + // Check if the org slug from the URL params doesn't match + // the active org slug from the user's session. + // If they don't match, show an error message and the list of valid Organizations. if (!organization || organization.slug != params.slug) { return ( <> -

Sorry, organization {params.slug} is not valid.

+

Sorry, Organization {params.slug} is not valid.

{organization && `Welcome to organization ${organization.name}`} + // Access the org name from the `Organization` object + return
{organization && `Welcome to Organization ${organization.name}`}
} ```
diff --git a/docs/guides/organizations/overview.mdx b/docs/guides/organizations/overview.mdx index f2bc323b73..6579784539 100644 --- a/docs/guides/organizations/overview.mdx +++ b/docs/guides/organizations/overview.mdx @@ -1,190 +1,50 @@ --- title: Organizations -description: Learn how to use Clerk Organizations to build scalable B2B auth features, user management, role based access control (RBAC), and per-organization invitation flows into your B2B SaaS. +description: Learn what Clerk Organizations are, how they work, and how to build secure multi-tenant B2B applications with team workspaces, Role-Based Access Control, and streamlined enrollment. metadata: - title: Overview - Build a B2B/B2C multi-tenant SaaS with Clerk Organizations + title: Organizations - Build multi-tenant B2B applications --- -Organizations are a flexible and scalable way to manage users and their access to resources within your Clerk application. With organizations, you can assign specific roles and permissions to users, making them useful for managing projects, coordinating teams, or facilitating partnerships. +Organizations let you group users with Roles and Permissions. This lets you build multi-tenant B2B apps like Slack (workspaces), Linear (teams), or Vercel (projects) where users switch between different team contexts. -> [!NOTE] -> To explore organizations in Clerk, check out the demo apps: -> [https://github.com/clerk/orgs](https://github.com/clerk/orgs) - -## Enable organizations in your application - -Organizations are disabled by default. - -To enable organizations: - -1. In the Clerk Dashboard, navigate to the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page. -1. Select **Enable Organizations**. - -Once organizations are enabled, you will be presented with the default settings, roles, and permissions that are applied to all organizations in that application instance. The following sections will explain these settings in more detail. - -## Roles and permissions - -Roles determine a user's level of access and permissions within an organization. Learn more about [how roles and permissions work and how to create your own with Clerk](/docs/guides/organizations/roles-and-permissions). - -## Membership limit - -There is no limit to the number of organizations a user can be a member of. - -However, there is a limit to how many total members can be in a single organization. By default, the membership limit is set to 5 members. To change this limit, scroll to the **Default membership limit** section and update the membership limit. - -If you are on the Free plan, you can update the membership limit to a maximum of 5 members. - -If you have the Pro plan, you can set the membership limit to unlimited. - -You can also change this limit on a per-organization basis: - -1. In the top in the Clerk Dashboard, select [**Organizations**](https://dashboard.clerk.com/~/organizations). -1. Select the organization you want to update. -1. In the **Membership limit** section, update the membership limit. Note that this will not apply to organizations that already exist. - -## Allow new members to delete organizations - -By default, organizations are deletable. Any member with the "Delete organization" permission can delete an organization. To prevent organizations from being deleted, you can disable the ability to delete organizations by following these steps: - -1. In the Clerk Dashboard, navigate to the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page. -1. Disable **Allow new members to delete organizations**. Note that this will not apply to organizations that already exist. - -## Verified domains - -Verified domains can be used to streamline enrollment into an organization. For example, if the domain `@clerk.com` is added to an organization, any user with a `@clerk.com` email address can be automatically invited or be suggested to join this organization. This feature is useful for organizations that want to restrict membership to users with specific email domains. See the [guide on verified domains](/docs/guides/organizations/verified-domains) for more information. - -## Allow Personal Accounts - -In the Clerk Dashboard, there are two types of workspaces: - -- **Personal account**: A Personal Account/workspace is a user's unique, individual space, independent of any organization. -- **Organization workspace**: An organization workspace is owned and managed by an organization, which can have multiple members, also known as collaborators. The organization workspace that a user is currently viewing is called the [Active Organization](!active-organization). - -Most multi-tenant applications want every user to be part of an organization rather than operating in an isolated Personal Account. Accordingly, **Personal Accounts are disabled by default** once you enable organizations. After signing up, [a user must create or join an organization before they can proceed](/docs/guides/configure/session-tasks). - -To enable Personal Accounts for your application, toggle **Allow Personal Accounts** in the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page. - -> [!IMPORTANT] -> Personal accounts being disabled by default was released on August 22, 2025. Applications created before this date will not be able to see the **Allow Personal Accounts** setting, because Personal Account were enabled by default. - -## Organization slugs - -Organization slugs are human-readable URL identifiers that help users reference which organization they're working in. - -To enable it, navigate to the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page in the Clerk Dashboard. - -When enabled, organization slugs will be displayed in the [``](/docs/reference/components/organization/create-organization), [``](/docs/reference/components/organization/organization-list), and [``](/docs/reference/components/organization/organization-switcher) components. - -> [!IMPORTANT] -> Organization slugs are disabled by default for applications created after October 7, 2025. For applications created before this date, you can opt to disable it. - -## Active organization +Users can belong to multiple Organizations, and Clerk provides the Organization context (memberships, Roles, and the Active Organization) in each session. You can then use this context to control what data to show and what actions to allow. -When a user is a member of an organization, they can switch between different organizations. The organization workspace that a user is currently viewing is called the **Active Organization**. The Active Organization determines which organization-specific data the user can access and which role and related permissions they have within the organization. - -When Personal Accounts are disabled (the default), users must select or create an organization to continue. This is handled automatically in the [session tasks flow](/docs/guides/configure/session-tasks). - -When Personal Accounts are enabled, users initially sign in to their Personal Account with **no** Active Organization set. The easiest way to allow users to set an organization as active is to use the [``](/docs/reference/components/organization/organization-switcher) component. If the prebuilt components don't meet your specific needs or if you require more control over the logic, you can also use the `setActive()` method, which is returned by the [`useOrganizationList()`](/docs/reference/hooks/use-organization-list) hook. If you aren't using hooks, you can access the `setActive()` method from the [`Clerk`](/docs/reference/javascript/clerk#set-active) object. - -## Monthly Active Organization (MAO) - -The number of organizations you can have in a single Clerk application depends on your [Clerk plan](/pricing){{ target: '_blank' }} and the type of instance (development or production), and is measured by Monthly Active Organizations (MAOs). An MAO is an organization with at least two users that have signed in that month, at least one of which must have interacted with the organization during the current billing cycle. - -With the Free plan: - -- In development instances, you can have _up to_ 50 MAOs in a single Clerk application. Each MAO can have _up to_ 5 members. -- In production instances, you can have up to 100 MAOs in a single Clerk application. Each MAO can have up to 5 members. - -With the Pro plan: - -- In development instances, you can have an unlimited number of MAOs in a single Clerk application _for free_. Each MAO can have an unlimited number of members. -- In production instances, you can have up to 100 MAOs in a single Clerk application _for free_. Each MAO after the first 100 costs $1.00 per month. Each MAO can have an unlimited number of members. - -For more information on pricing, see the [pricing page](/pricing){{ target: '_blank' }}. - -If you need more organizations or custom pricing, contact the [sales team](/contact/sales){{ target: '_blank' }} to upgrade to the Enterprise plan. - -## Manage organizations - -As the application owner, you have control over all of the organizations within your application - both those created by you and those created by your users. You can create, update, and delete organizations, as well as manage their members and settings. - -There are two ways to manage organizations: - -- [In the Clerk Dashboard](#manage-organizations-in-the-clerk-dashboard) -- [In your application](#manage-organizations-in-your-application) - -### Manage organizations in the Clerk Dashboard - -To manage organizations in the Clerk Dashboard: - -1. In the top in the Clerk Dashboard, select [**Organizations**](https://dashboard.clerk.com/~/organizations). Here, you can view and manage all organizations in your application. -1. Select a specific organization to view its details, members, invitations, and settings. Here, you can update the organization's name, slug, logo, and public and private metadata. You can also set the organization's [membership limit](#membership-limit). - -### Manage organizations in your application - -For managing organizations in your application, Clerk provides a set of prebuilt components: - -- [``](/docs/reference/components/organization/create-organization) - A form for a user to create a new organization. -- [``](/docs/reference/components/organization/organization-profile) - A profile page for the user's currently Active Organization. -- [``](/docs/reference/components/organization/organization-list) - A list of organizations that a user is a member of. -- [``](/docs/reference/components/organization/organization-switcher) - A dropdown menu that handles all organization flows. It allows a user to create an organization, switch between organizations, and view their organization's profile, which allows them to manage the organization's settings, invitations, and current members. If [Personal Accounts are enabled](/docs/guides/organizations/overview#allow-personal-accounts), users can also switch to their Personal Account. - -If the prebuilt components don't meet your specific needs or if you require more control over the logic, you can rebuild and customize the existing Clerk flows using the Clerk API. See the [custom flows](/docs/guides/development/custom-flows/overview) for more information. - -## Create an organization - -There are two ways to create an organization: - -- [In the Clerk Dashboard](#create-an-organization-in-the-clerk-dashboard) -- [In your application](#create-an-organization-in-your-application) - -How many organizations you can create depends on how many [MAOs](#monthly-active-organization-mao) you have. - -### Create an organization in the Clerk Dashboard - -To create an organization in the Clerk Dashboard: - -1. In the top in the Clerk Dashboard, select [**Organizations**](https://dashboard.clerk.com/~/organizations). -1. Select the **Create Organization** button. -1. Enter the organization's name. Optionally, upload the organization's logo, enter the organization's slug, and select the organization's owner. The slug is a unique identifier for the organization that is used in URLs, such as `example-name`. - -### Create an organization in your application +> [!NOTE] +> To explore Organizations in Clerk, check out the [demo apps](https://github.com/clerk/orgs). -By default, users have the permission to create organizations within your application. To configure this permission for all users: +## How do Organizations work? -1. In the Clerk Dashboard, navigate to the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page. -1. At the bottom of the page, in the **Limit creation** section, enable/disable **Allow new users to create organizations**. You can also configure the number of organizations that can be created by each user. By default, each user can create an unlimited number of organizations. +Organizations live within your Clerk application. Each application can contain multiple Organizations, and each Organization can have multiple users. You define [Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions) once at the application level, and they apply across all Organizations within that application. -If you want to only configure this permission for a specific user, you can override it on a per-user basis on the user's profile page in the Clerk Dashboard: +![Relationship between Clerk Organization, users, Roles and Permissions](/docs/images/orgs/relationship-diagram.jpg) -1. In the top in the Clerk Dashboard, select [**Users**](https://dashboard.clerk.com/~/users). -1. Select the user you want to update. -1. In the **User permissions** section, enable/disable **Allow user to create organizations**. +The Organization that a user is currently viewing is called the **Active Organization**. The Active Organization determines which Organization-specific data the user can access and which Role and related Permissions they have within the Organization. -When a user creates an organization, they become the organization's admin. As the organization's admin, they have full control over the organization, including the ability to update the organization's settings, invite users to join the organization, and manage the organization's members. +Clerk measures Organization usage through **Monthly Active Organizations (MAOs)**. An MAO is an Organization with at least two users that have signed in that month, where at least one has interacted with the Organization during the current billing cycle. Free plans include up to 50 MAOs in development and 100 in production. Pro plans offer unlimited development MAOs and start at 100 free production MAOs, then $1 per additional MAO. Refer to the [pricing page](/pricing){{ target: '_blank' }} for complete details. -A single user within one of your applications can create _up to_ 100 organizations in that application. If you need users to be able to create more organizations than this, [contact support](/contact/support){{ target: '_blank' }} to have the limit raised. +## Core workflow -The easiest way to allow users to create organizations is to use the [``](/docs/reference/components/organization/create-organization) and/or [``](/docs/reference/components/organization/organization-switcher) components. The `` component is more comprehensive, as it handles all organization flows. +The core workflow when working with Organizations can follow something along the lines of: -## Organization invitations +1. **Create**: You can create Organizations [in the Clerk Dashboard](https://dashboard.clerk.com/~/organizations), or end users can create them in your application through prebuilt components or APIs. Each Organization has a profile, settings, and [metadata](/docs/guides/organizations/metadata). Users can belong to multiple Organizations and switch between them with the [``](/docs/reference/components/organization/organization-switcher) component. Learn more about [creating and managing Organizations](/docs/guides/organizations/create-and-manage). -[Learn how to create and revoke organization invitations](/docs/guides/organizations/invitations). +1. **Add members**: You can add members to Organizations in different ways depending on your needs: -## Manage enterprise connections + - [**Invitations**](/docs/guides/organizations/add-members/invitations) for bottom-up adoption, where individual users invite teammates with precise control over roles. + - [**Verified Domains**](/docs/guides/organizations/add-members/verified-domains) for company-wide rollouts, where Clerk automatically invites users with matching email domains (who can join immediately) or suggests they join (requiring admin approval). + - [**Enterprise Connections**](/docs/guides/organizations/add-members/sso) (SAML or OIDC) for top-down deployments managed by IT with centralized authentication through an Identity Provider (IdP). -Single Sign-On (SSO) can be configured at the organization level, allowing organizations to use their own Identity Provider (IdP) for authentication. These are called **enterprise connections**. When configured: + You can combine these approaches: use manual invitations for external contractors alongside domain-based enrollment for employees. The Active Organization determines which members and Roles apply to the current context. -- Users can sign in through their organization's configured IdP -- Users are **automatically added as members** of the organization upon successful authentication -- Organizations can maintain their existing identity management workflows -- SAML 2.0 and OIDC protocols are supported +1. **Control access**: You can manage access to content or entire pages using Roles and Permissions. Default admin and member Roles cover common cases, while custom Roles and Permissions provide fine-grained access for more complex needs. You can perform [authorization checks](!authorization-check) in both frontend and backend code. -For instructions on how to set up and manage SSO for your organizations, see the [dedicated guide](/docs/guides/organizations/sso). +Beyond these core steps, you can also monitor Organization health and growth with analytics in the Clerk Dashboard. This helps you spot which Organizations are growing, staying active, or dropping off, so you know what's working and where you might need attention. ## Next steps -- [Learn how to limit access to content or entire routes based on a user's role or permissions](/docs/guides/secure/authorization-checks) -- [Learn how to restrict memberships to an organization based on their email domain](/docs/guides/organizations/verified-domains) -- [Learn how to manually invite users to an organization](/docs/guides/organizations/invitations) -- [Learn how to automatically add users to an organization based on their email domain](/docs/guides/organizations/sso) +Now that you understand what Organizations are and how they work, here's how to implement them: + +- [Configure Organization settings](/docs/guides/organizations/configure) +- [Create and manage Organizations](/docs/guides/organizations/create-and-manage) +- [Invite members](/docs/guides/organizations/add-members/invitations) +- [Set up Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions) diff --git a/docs/guides/organizations/roles-and-permissions.mdx b/docs/guides/organizations/roles-and-permissions.mdx deleted file mode 100644 index 8b5c9046c8..0000000000 --- a/docs/guides/organizations/roles-and-permissions.mdx +++ /dev/null @@ -1,144 +0,0 @@ ---- -title: Roles and permissions -description: Step-by-step guide on how to implement role based access control (RBAC) in B2C/B2B SaaS apps. You can set as many custom roles, assign privileges and access permissions, all using Clerk Organizations. -metadata: - title: B2B/B2C roles and permissions with Clerk Organizations ---- - - - -Clerk supports modeling your own custom role and permissions to control access to resources within your application when you use [organizations](/docs/guides/organizations/overview). - -## Roles - -Roles determine a user's level of access to the organization. You can extend a role's privileges and access to resources by adding [permissions](#permissions). - -### Default roles - -For each instance, there are currently two default roles: - -- **Admin (`org:admin`)** - Offers full access to organization resources. Members with the admin role have all of the [system permissions](#system-permissions). They can fully manage the organization and organization memberships. -- **Member (`org:member`)** - Offers limited access to organization resources. Access to organization resources is limited to the "Read members" and "Read billing" permissions only, by default. They cannot manage the organization and organization memberships, but they can view information about other members in it. - -### The **Creator** role - -When a user creates a new organization, they're automatically added as its first member and assigned the organization's designated **Creator** role. By default, that role is `org:admin`. - -You cannot delete an organization role if it's used as the organization's **Creator** role. But, you _can_ reassign the **Creator** role to any other role with the right permissions. For example, if you want to delete the `admin` role, you will have to assign another role as the **Creator** role. - -The **Creator** role must _at least_ have the following [system permissions](#system-permissions): - -- Manage members (`org:sys_memberships:manage`) -- Read members (`org:sys_memberships:read`) -- Delete organization (`org:sys_profile:delete`) - -To reassign the **Creator** role: - -1. In the Clerk Dashboard, navigate to [**Roles & Permissions**](https://dashboard.clerk.com/~/organizations-settings/roles). -1. [Create a new role](#custom-roles) or use an existing role from the list. -1. Ensure that **Manage members**, **Read members**, and **Delete organization** system permissions are selected for the role. -1. Open the three dots icon for the role. -1. From the dropdown, select the **Set as Creator role** option. - -### The **Default** role for members - -New organization members are initially assigned the **Default** role. By default, that role is `org:member`. This role is used as a pre-filled default in `` invitations and for organization enrollment with [verified domains](/docs/guides/organizations/verified-domains). - -You cannot delete an organization role if it's used as the organization's **Default** role. But, you _can_ reassign the **Default** role to any other role. - -To reassign the **Default** role: - -1. In the Clerk Dashboard, navigate to [**Roles & Permissions**](https://dashboard.clerk.com/~/organizations-settings/roles). -1. [Create a new role](#custom-roles) or use an existing role from the list. -1. Open the three dots icon for the role. -1. From the dropdown, select the **Set as Default role** option. - -### Custom roles - -You can create up to 10 custom organization roles per application instance to meet your application needs. If you need more than 10 roles, [contact support](/contact/support){{ target: '_blank' }}. - -Custom roles can be granted permissions and access. For example, you can create a new role of **Billing** (`org:billing`) which can be used to group users who belong to a specific department of the organization and have permission to manage credit card information, invoices, and other resources related to billing. - -To create a new role: - -1. In the Clerk Dashboard, navigate to [**Roles & Permissions**](https://dashboard.clerk.com/~/organizations-settings/roles) -1. Select **Add role**. -1. Give the role a name, a key to reference it by, and a description. The final key will follow the format `org:`. -1. Select **Save**. - -### Change a user's role - -You can change a user's role in the Clerk Dashboard, or in your application, such as in the [``](/docs/reference/components/organization/organization-switcher) component. - -To change a user's role in the Clerk Dashboard: - -1. In the top in the Clerk Dashboard, select [**Organizations**](https://dashboard.clerk.com/~/organizations) and select an organization. -1. Select the **Members** tab. -1. In the list of members, find the one whose role you want to change. -1. Select another role from their role dropdown. - -### Delete a role - -You cannot delete a role that is still assigned to members of an organization. Change the members to a different role before completing the following steps. - -1. In the Clerk Dashboard, navigate to [**Roles & Permissions**](https://dashboard.clerk.com/~/organizations-settings/roles). -1. Select the three dots icon next to the role. -1. Select **Delete role**. - -## Permissions - -Permissions grant users privileged access to resources and operations, like creating and deleting. Clerk supports two types of permissions: **system permissions** and **custom permissions**. - -### System permissions - -Clerk provides a set of system permissions that power [Clerk's Frontend API](/docs/reference/frontend-api){{ target: '_blank' }} and [organization-related Clerk components](/docs/reference/components/overview). These permissions serve as the baseline required for Clerk to operate effectively. - -Clerk's system permissions consist of the following: - -- Manage organization (`org:sys_profile:manage`) -- Delete organization (`org:sys_profile:delete`) -- Read members (`org:sys_memberships:read`) -- Manage members (`org:sys_memberships:manage`) -- Read domains (`org:sys_domains:read`) -- Manage domains (`org:sys_domains:manage`) -- Read billing (`org:sys_billing:read`) -- Manage billing (`org:sys_billing:manage`) - -You can assign these system permissions to any role. - -> [!WARNING] -> System permissions aren't included in [session claims](/docs/guides/sessions/session-tokens#default-claims). To check permissions on the server-side, you must [create custom permissions](#custom-permissions). - -### Custom permissions - -Custom permissions let you define fine-tuned access control within your organization. Each permission is tied to a feature, and can be assigned to one or more roles. To create a custom permission, you must first create a role (e.g. **sales**) and a feature within that role (e.g. **invoices**). Once both exist, you can define specific permissions (e.g. **create**) related to that feature. - -To create a new permission: - -1. In the Clerk Dashboard, navigate to [**Roles & Permissions**](https://dashboard.clerk.com/~/organizations-settings/roles). -1. [Create a new role](#custom-roles) or use an existing role from the list. -1. Under **Custom permissions**, select **Create permission** under the feature you want to create the permission for. If there are no features, you'll need to create a new one first. Select **Create feature** and fill in the required fields. Once finished, the newly created feature will appear in the list, and the **Create permission** button will appear. -1. Give the permission a name, a key to reference it by, and a description. The final key will follow the format `org::`. - > [!NOTE] - > Common permission values could be: - > - > - `create` — to allow creating resources - > - `read` — to allow reading/viewing resources - > - `update/manage` — to allow updating/editing resources - > - `delete` — to allow deleting resources - > - > For example, you could create a new permission called **Create invoices** (`org:invoices:create`) which allows only users with this permission to edit invoices. Then, you could assign this permission to a role, or multiple roles, such as **Billing** (`org:billing`) or **Sales** (`org:sales`). -1. Select **Create permission**. - -You can also create a custom permission by navigating to the [**Features**](https://dashboard.clerk.com/~/features) tab in the Clerk Dashboard. - -## Verify a user's role or permission - -It's best practice to always verify whether or not a user is **authorized** to access sensitive information, important content, or exclusive features. **Authorization** is the process of determining the access rights and privileges of a user, ensuring they have the necessary permissions to perform specific actions. To perform authorization checks using a user's role or permission, see the [guide on authorizing users](/docs/guides/secure/authorization-checks). - -## Next steps - -- [Learn how to limit access to content or entire routes based on a user's role or permissions](/docs/guides/secure/authorization-checks) -- [Learn how to automatically invite users to an organization based on their email domain](/docs/guides/organizations/verified-domains) -- [Learn how to manually invite users to an organization](/docs/guides/organizations/invitations) -- [Learn how to automatically add users to an organization based on their email domain](/docs/guides/organizations/sso) diff --git a/docs/guides/organizations/sso.mdx b/docs/guides/organizations/sso.mdx deleted file mode 100644 index 4b68f8718e..0000000000 --- a/docs/guides/organizations/sso.mdx +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Organization-level enterprise SSO -description: Integrate as many enterprise SSO methods within Clerk Organizations. Enable SAML SSO, OAuth/OIDC, and other secure MFA/single sign-on options for B2B SaaS apps. -metadata: - title: Set up organization-level SAML and OIDC for B2B/B2C apps ---- - -Clerk supports enabling enterprise SSO connections for specific organizations. When users sign up or sign in using an organization's enterprise connection, they're automatically added as members of that organization and assigned the [default role](/docs/guides/organizations/roles-and-permissions#the-default-role-for-members), which can be either `member` or `admin`. - -## Add an enterprise SSO connection for an organization - -Clerk supports enterprise SSO via [SAML](/docs/guides/configure/auth-strategies/enterprise-connections/overview#saml) or via the [OpenID Connect (OIDC) protocol](/docs/guides/configure/auth-strategies/enterprise-connections/overview#oidc), either through EASIE or by integrating with any OIDC-compatible provider. - -To add an enterprise SSO connection for an organization, follow the appropriate guide based on the platform you want to use, such as the [Google SAML guide](/docs/guides/configure/auth-strategies/enterprise-connections/saml/google). When configuring the connection in the Clerk Dashboard, there will be an option to select the **Organization** for which you want to enable this connection. If you don't select an organization, the connection will be added for your entire application. - -> [!WARNING] -> A domain used for enterprise SSO can't be used as a [verified domain](/docs/guides/organizations/verified-domains) for the same organization. - -## Onboarding flows - -The two common onboarding flows for organizations with enterprise SSO are to either create an organization first or to have users initiate the setup themselves. - -#### Organization created first (top-down approach) - -This flow is common for enterprise sales where the relationship is established before users access the application. - -1. [Create an organization](/docs/guides/organizations/overview#create-an-organization) for your customer through the Clerk Dashboard. -1. Collaborate with the customer's IT administrator to obtain the necessary configuration details. -1. Configure the enterprise SSO connection for the organization. -1. Invite users to the organization, who can then sign in using enterprise SSO. - -#### User-initiated setup (bottom-up approach) - -This flow is common when individual users try the product before company-wide adoption. - -1. An end user signs up to evaluate your application, starting with an individual account. -1. After adopting the application, the user [creates an organization](/docs/guides/organizations/overview#create-an-organization) for their company. -1. Configure enterprise SSO for the organization through the Clerk Dashboard. -1. All subsequent users from that organization can now sign in using enterprise SSO. - -## Enforce enterprise SSO by domain - -Enterprise SSO connections are enforced on a per-domain basis in organizations, enabling flexible access management: - -- Configure enterprise SSO for your primary domain (e.g., `company.com`) to enforce enterprise SSO authentication for employees. -- Add additional domains without enterprise SSO for external collaborators (e.g., contractors, consultants). -- Each domain in an organization can have different authentication requirements. - -## Manage memberships - -### Remove a member from your organization - -When a user is tied to an organization through their enterprise connection, they cannot leave the organization themselves, but they can be removed either in the Clerk Dashboard, using [Clerk's Backend API](/docs/reference/backend-api/tag/organization-memberships/delete/organizations/\{organization_id}/memberships/\{user_id}){{ target: '_blank' }} endpoint, or by another organization member with the [manage members permission](/docs/guides/organizations/roles-and-permissions#system-permissions) (`org:sys_memberships:manage`). However, the user will be added back to the organization on next sign-in, unless they are removed from the IdP or the enterprise connection is no longer associated with the organization. - -## Update an organization from an existing enterprise connection - -When transitioning an enterprise connection to a new organization, existing members will remain part of the original organization. However, they will automatically join the new organization upon their next sign-in. - -To remove members from the original organization, you have two options: utilize [Clerk's Backend API](/docs/reference/backend-api/tag/organization-memberships/delete/organizations/\{organization_id}/memberships/\{user_id}){{ target: '_blank' }} or manage memberships directly through the Clerk Dashboard. diff --git a/docs/guides/organizations/verified-domains.mdx b/docs/guides/organizations/verified-domains.mdx deleted file mode 100644 index afbf5dc40c..0000000000 --- a/docs/guides/organizations/verified-domains.mdx +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Verified domains -description: Build organization-specific or tenant-isolated authentication flows that only authorized users with matching domains can join, using Verified Domains within Clerk Organizations. -metadata: - title: Verified domains within Clerk Organizations (Step-by-Step) ---- - -Clerk's **verified domains** feature is useful for organizations that want to restrict membership to users with specific email domains, and automatically invite or suggest users with that domain to join an organization. For example, if the domain `@clerk.com` is verified, any user with an email address ending in `@clerk.com` can be automatically invited or be suggested to join an organization with that domain. The role assigned to this user will be the role set as the [**Default** role](/docs/guides/organizations/roles-and-permissions#the-default-role-for-members) in the organization settings page. - -A verified domain cannot be a disposable domain or common email provider. For example, you cannot create a verified domain for `@gmail.com`. - -> [!WARNING] -> A verified domain can't be added if it's already in use for the [organization's SSO](/docs/guides/organizations/sso). - -The easiest way to add and verify domains, and manage all settings related to verified domains is to use Clerk's [``](/docs/reference/components/organization/organization-switcher) component. - -## Enable verified domains - -Enabling verified domains applies to all organizations and cannot currently be managed on a per-organization basis. - -In order to enable this feature: - -1. In the Clerk Dashboard, navigate to the [**Organizations Settings**](https://dashboard.clerk.com/~/organizations-settings) page. -1. In the **Organization options** section, toggle on **Enable verified domains**. -1. The following enrollment modes will appear that can be enabled for verified domains: - - - [**Automatic invitation**](#automatic-invitations) - Users are automatically invited to join the organization when they sign-up and can join anytime. - - [**Automatic suggestion**](#automatic-suggestions) - Users receive a suggestion to request to join, but must be approved by an admin before they are able to join the organization. - - When a user with the `org:sys_domains:manage` permission has added and verified a domain in your application, they can enable an enrollment mode. **Only one enrollment mode can be enabled for a verified domain at a time.** - -### Automatic invitations - -After sign-up, a user will receive an **invitation** for the organization if their email's domain matches the verified domain. If your app uses the `` component, the user will see a notification on the component and also receive an email prompting them to accept the invitation. - -When they open the component, they will see a **Join** button next to the organization they were invited to. Selecting the button will accept the invitation and the user will instantly be added as a member of the organization. - -### Automatic suggestions - -After sign-up, a user will receive a **suggestion** for the organization if their email's domain matches the verified domain. If your app uses the `` component, the user will see a **Request to join** button next to the organization. Selecting the button will send a [membership request](#membership-requests) to the organization. - -### Membership requests - -Membership requests are requests from users who saw an organization suggestion and requested to join an organization. Membership requests are only available for organizations that have the **Verified domains** feature enabled and the **Automatic suggestions** feature enabled in both the Dashboard and for the specific domain. - -When a user sends an organization membership request, users with the `org:sys_memberships:manage` permission (by default, admins) are notified through both: - -- A notification badge on the `` component. -- An email alert. - -Regardless of how they are notified, membership requests can only be reviewed and managed through the `` component. Selecting the notification badge will open the organization management page, where the request appears under `Members > Requests`. A request must be approved before the user is added to the organization. - -## Add and verify domains - -Domains can be added and verified under an organization by any user with the `org:sys_domains:manage` permission. By default, admins have this permission. To add and verify domains in the [``](/docs/reference/components/organization/organization-switcher) component, select the **General** tab. There will be a **Verified domains** section. - -Domains can be verified through an email verification code sent to an email that matches the domain. If the user adding the domain already has a verified email using that domain in their account, the domain will be automatically verified. - -An application instance may only have one verified domain of the same name, and an organization may only have one domain of the same name (verified or unverified). - -You can create up to 10 domains per organization to meet your needs. If you need more than 10 domains, [contact support](/contact/support){{ target: '_blank' }}. - -### Custom flow - -If Clerk's [``](/docs/reference/components/organization/organization-switcher) does not meet your specific needs or if you require more control over the logic, you can use the Clerk API to add and verify a domain and update the domain's enrollment mode. Here's an example of how you can do this: - -```tsx -const { organization, domains } = useOrganization() - -// create domain -const domain = await organization.createDomain('example.com') - -// prepare email verification -domain.prepareAffiliationVerification({ affiliationEmailAddress: 'foo@example.com' }) - -// attempt email verification -domain.attemptAffiliationVerification({ code: '123456' }) - -// update domain enrollment mode -domain.updateEnrollmentMode({ enrollmentMode: 'automatic_invitation' }) -``` diff --git a/docs/guides/secure/authorization-checks.mdx b/docs/guides/secure/authorization-checks.mdx index c1a16b01b7..b54c5cdf2e 100644 --- a/docs/guides/secure/authorization-checks.mdx +++ b/docs/guides/secure/authorization-checks.mdx @@ -1,6 +1,6 @@ --- -title: Authorize users -description: Learn how to verify and validate user Roles and Permissions within Clerk to maintain secure access control. We provide a collection of utility functions and components that allow developers to perform authorization checks. +title: Authorization checks +description: Learn how to verify and validate user Roles and Permissions within Clerk to maintain secure access control. metadata: title: Verifying user permissions with Clerk --- @@ -10,7 +10,7 @@ It's best practice to always verify whether or not a user is **authorized** to a Clerk provides two main features that can be used to implement authorization checks: - [Organizations](/docs/guides/organizations/overview) - - Users can be assigned [Roles and Permissions](/docs/guides/organizations/roles-and-permissions#permissions) + - Users can be assigned [Roles and Permissions](/docs/guides/organizations/control-access/roles-and-permissions#permissions) - Useful for Role-based and Permission-based access control - [Billing](/docs/guides/billing/overview) - Users can subscribe to Plans and Features @@ -21,8 +21,8 @@ You can use either options independently or combine them together depending on y There are a few methods to perform authorization checks: - The [`has()`](/docs/reference/backend/types/auth-object#has) helper **(recommended)**: returns `false` if the user is unauthorized. - - Benefits: it offers flexibility and control over the response; if a user is not authorized, you can choose how your app responds. - - Limitations: when checking for Permissions, it only checks for custom Permissions. To check for system Permissions, you have to verify the user's Role instead, which isn't as flexible. + - Benefits: it can be used both client-side and server-side. It offers flexibility and control over the response; if a user is not authorized, you can choose how your app responds. + - Limitations: when checking for Permissions, it only checks for Custom Permissions. To check for System Permissions, you have to verify the user's Role instead, which isn't as flexible. - The [``](/docs/reference/components/control/protect) component: prevents content from rendering if the user is unauthorized. - Benefits: it can be used both client-side and server-side (in Server Components). - Limitations: this component only **visually hides** its children when the current user is not authorized. The contents of its children remain accessible via the browser's source code even if the user fails the authorization check. Do not use this component to hide sensitive information that should be completely inaccessible to unauthorized users. For truly sensitive data, it's recommended to use `has()` to perform authorization checks on the server before sending the data to the client. @@ -38,7 +38,7 @@ This guide will show you how to implement authorization checks in order to prote ## Important considerations - When doing authorization checks, it's recommended to use Permission-based over Role-based, and Feature-based over Plan-based authorization, as these approaches are more granular, flexible, and more secure. - - Note: Using `has()` **on the server-side** to check Permissions works only with **Custom Permissions**, as [System Permissions](/docs/guides/organizations/roles-and-permissions#system-permissions) aren't included in the session token claims. To check System Permissions, verify the user's Role instead. + - Note: Using `has()` **on the server-side** to check Permissions works only with **Custom Permissions**, as [System Permissions](/docs/guides/organizations/control-access/roles-and-permissions#system-permissions) aren't included in the session token claims. To check System Permissions, verify the user's Role instead. - Checking for a Role or Permission depends on the user having an [Active Organization](!active-organization). Without an Active Organization, the authorization checks will likely always evaluate to false by default. - If you would like to perform Role-based authorization checks **without** using Clerk's Organizations feature, see [the Role Based Access Control (RBAC) guide](/docs/guides/secure/basic-rbac). - If you have both Organizations and Billing enabled, a Permission check will only work if the Feature part of the Permission key (`org::`) **is a Feature included in the Organization's active Plan**. For example, say you want to check if an Organization member has the Custom Permission `org:teams:manage`, where `teams` is the Feature. Before performing the authorization check, you need to ensure that the user's Organization is subscribed to a Plan that has the `teams` Feature. If not, the authorization check will always return `false`, _even if the user has the Custom Permission_. diff --git a/docs/guides/secure/basic-rbac.mdx b/docs/guides/secure/basic-rbac.mdx index a404f0eead..f2036fb818 100644 --- a/docs/guides/secure/basic-rbac.mdx +++ b/docs/guides/secure/basic-rbac.mdx @@ -4,7 +4,7 @@ description: Learn how to leverage Clerk's publicMetadata to implement your own sdk: nextjs --- -To control which users can access certain parts of your app, you can use the [Roles](/docs/guides/organizations/roles-and-permissions#roles) feature. Although Clerk offers Roles as part of the [Organizations](/docs/guides/organizations/overview) feature set, not every app implements Organizations. **This guide covers a workaround to set up a basic Role Based Access Control (RBAC) system for products that don't use Clerk's Organizations or Roles.** +To control which users can access certain parts of your app, you can use the [Roles](/docs/guides/organizations/control-access/roles-and-permissions#roles) feature. Although Clerk offers Roles as part of the [Organizations](/docs/guides/organizations/overview) feature set, not every app implements Organizations. **This guide covers a workaround to set up a basic Role Based Access Control (RBAC) system for products that don't use Clerk's Organizations or Roles.** This guide assumes that you're using Next.js App Router, but the concepts can be adapted to Next.js Pages Router and Remix. diff --git a/docs/guides/secure/features.mdx b/docs/guides/secure/features.mdx index 5a86fc19fa..bb16ac76ec 100644 --- a/docs/guides/secure/features.mdx +++ b/docs/guides/secure/features.mdx @@ -7,7 +7,7 @@ Features are specific capabilities or functionalities in your application that y Features can be used in two ways: -- With Clerk's [Organizations](/docs/guides/organizations/overview) feature to create Custom Permissions. Custom Permissions are always tied to a Feature, and are formatted as `org::`. For example, you could create a Feature called **invoices** and then create a new Permission called **create invoices**. The Custom Permission's key would be `org:invoices:create`. Learn more about [Custom Permissions](/docs/guides/organizations/roles-and-permissions). +- With Clerk's [Organizations](/docs/guides/organizations/overview) feature to create Custom Permissions. Custom Permissions are always tied to a Feature, and are formatted as `org::`. For example, you could create a Feature called **invoices** and then create a new Permission called **create invoices**. The Custom Permission's key would be `org:invoices:create`. Learn more about [Custom Permissions](/docs/guides/organizations/control-access/roles-and-permissions). - With Clerk's Billing feature to create Features specific to a Subscription Plan. See the [Billing docs](/docs/guides/billing/overview) for more information. To manage your Features, navigate to the [**Features**](https://dashboard.clerk.com/~/features) page in the Clerk Dashboard. diff --git a/docs/guides/sessions/manual-jwt-verification.mdx b/docs/guides/sessions/manual-jwt-verification.mdx index f59451147f..c4c7edfcdc 100644 --- a/docs/guides/sessions/manual-jwt-verification.mdx +++ b/docs/guides/sessions/manual-jwt-verification.mdx @@ -43,7 +43,7 @@ The following example uses the `authenticateRequest()` method to verify the sess ### Optional: Check for a `sts` claim - If you are using Clerk's [Organizations](/docs/guides/organizations/overview) feature and [have not enabled Personal Accounts](/docs/guides/organizations/overview#allow-personal-accounts), users are _required to be part of an Organization before accessing your application_. If the user has completed registration, but is not yet part of an Organization, a valid session token will be created, but the token will contain a `sts` (status) claim set to `pending`. You may want to reject requests to your backend with pending statuses to ensure that users are not able to work around the Organization requirement. + If you are using Clerk's [Organizations](/docs/guides/organizations/overview) feature and [have not enabled Personal Accounts](/docs/guides/organizations/configure#allow-personal-accounts), users are _required to be part of an Organization before accessing your application_. If the user has completed registration, but is not yet part of an Organization, a valid session token will be created, but the token will contain a `sts` (status) claim set to `pending`. You may want to reject requests to your backend with pending statuses to ensure that users are not able to work around the Organization requirement. ### Finished diff --git a/docs/manifest.json b/docs/manifest.json index d7f54f00e5..d1f0e4f5d3 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -90,6 +90,10 @@ { "title": "Hybrid rendering", "href": "/docs/guides/development/hybrid-rendering" + }, + { + "title": "Get started with organizations", + "href": "/docs/guides/organizations/getting-started" } ] ] @@ -702,27 +706,59 @@ "href": "/docs/guides/organizations/overview" }, { - "title": "Verified domains", - "href": "/docs/guides/organizations/verified-domains" + "title": "Get started with organizations", + "href": "/docs/guides/organizations/getting-started" }, { - "title": "Roles and Permissions", - "href": "/docs/guides/organizations/roles-and-permissions" + "title": "Configure organizations", + "href": "/docs/guides/organizations/configure" }, { - "title": "Invitations", - "href": "/docs/guides/organizations/invitations" + "title": "Create and manage organizations", + "href": "/docs/guides/organizations/create-and-manage" }, { - "title": "Metadata", - "href": "/docs/guides/organizations/metadata" + "title": "Add members to an organization", + "collapse": true, + "items": [ + [ + { + "title": "Invitations", + "href": "/docs/guides/organizations/add-members/invitations" + }, + { + "title": "Verified domains", + "href": "/docs/guides/organizations/add-members/verified-domains" + }, + { + "title": "Enterprise SSO", + "href": "/docs/guides/organizations/add-members/sso" + } + ] + ] }, { - "title": "Manage enterprise SSO connections", - "href": "/docs/guides/organizations/sso" + "title": "Control access", + "collapse": true, + "items": [ + [ + { + "title": "Roles and permissions", + "href": "/docs/guides/organizations/control-access/roles-and-permissions" + }, + { + "title": "Check access", + "href": "/docs/guides/organizations/control-access/check-access" + } + ] + ] + }, + { + "title": "Set organization metadata", + "href": "/docs/guides/organizations/metadata" }, { - "title": "Use org slugs in URLs", + "title": "Use organization slugs in URLs", "href": "/docs/guides/organizations/org-slugs-in-urls" } ] diff --git a/docs/reference/astro/client-side-helpers/organization-store.mdx b/docs/reference/astro/client-side-helpers/organization-store.mdx index f2b74ea296..47d32e8b13 100644 --- a/docs/reference/astro/client-side-helpers/organization-store.mdx +++ b/docs/reference/astro/client-side-helpers/organization-store.mdx @@ -8,31 +8,23 @@ The `$organizationStore` store is used to retrieve attributes of the currently [ ## How to use the `$organizationStore` store -The following example demonstrates how to use the `$organizationStore` store to access the [`Organization`](/docs/reference/javascript/organization){{ target: '_blank' }} object, which allows you to access the current [Active Organization](!active-organization). +The following example demonstrates how to use the `$organizationStore` store to access the [`Organization`](/docs/reference/javascript/organization) object, which allows you to access the current [Active Organization](!active-organization). - ```tsx {{ filename: 'organization.tsx' }} + ```tsx {{ filename: 'components/Home.tsx' }} import { useStore } from '@nanostores/react' import { $organizationStore } from '@clerk/astro/client' export default function Home() { const organization = useStore($organizationStore) - if (organization === undefined) { - // Add logic to handle loading state - return null - } + // Add logic to handle loading state + if (organization === undefined) return

Loading...

- if (organization === null) { - // Add logic to handle no Active Organization state - return null - } + // Add logic to handle no Active Organization state + if (organization === null) return

Set an Active Organization to access this page.

- return ( -
-

This current organization is {organization.name}

-
- ) + return

This current Organization is {organization.name}

} ``` @@ -52,7 +44,7 @@ The following example demonstrates how to use the `$organizationStore` store to
-

This current organization is {{ organization.name }}

+

This current Organization is {{ organization.name }}

``` @@ -69,9 +61,7 @@ The following example demonstrates how to use the `$organizationStore` store to {:else if $organization === null} {:else} -
-

This current organization is {$organization.name}

-
+

This current Organization is {$organization.name}

{/if} ```
@@ -80,7 +70,7 @@ The following example demonstrates how to use the `$organizationStore` store to The following example demonstrates how to implement pagination for Organization memberships. The `memberships` state will be populated with the first page of the Organization's memberships. When the "Previous page" or "Next page" button is clicked, the `fetchMemberships` function will be called to fetch the previous or next page of memberships. -You can implement this pattern to any Clerk function that returns a [`ClerkPaginatedResponse`](/docs/reference/javascript/types/clerk-paginated-response){{ target: '_blank' }} object. +You can implement this pattern to any Clerk function that returns a [`ClerkPaginatedResponse`](/docs/reference/javascript/types/clerk-paginated-response) object. ```tsx {{ filename: 'members.tsx' }} @@ -100,9 +90,7 @@ You can implement this pattern to any Clerk function that returns a [`ClerkPagin }, [currentPage, organization]) const fetchMemberships = async () => { - if (!organization) { - return - } + if (!organization) return const { data } = await organization.getMemberships({ initialPage: currentPage, @@ -114,15 +102,11 @@ You can implement this pattern to any Clerk function that returns a [`ClerkPagin const fetchPrevious = () => setCurrentPage(currentPage - 1) const fetchNext = () => setCurrentPage(currentPage + 1) - if (organization === undefined) { - // Handle loading state - return null - } + // Add logic to handle loading state + if (organization === undefined) return

Loading...

- if (organization === null) { - // Handle no organization state - return null - } + // Add logic to handle no Active Organization state + if (organization === null) return

Set an Active Organization to access this page.

return (
@@ -159,9 +143,7 @@ You can implement this pattern to any Clerk function that returns a [`ClerkPagin const pageSize = 10 const fetchMemberships = async () => { - if (!organization.value) { - return - } + if (!organization.value) return const { data } = await organization.value.getMemberships({ initialPage: currentPage.value, @@ -171,9 +153,7 @@ You can implement this pattern to any Clerk function that returns a [`ClerkPagin } watchEffect(() => { - if (!organization.value) { - return - } + if (!organization.value) return fetchMemberships() }) @@ -184,10 +164,10 @@ You can implement this pattern to any Clerk function that returns a [`ClerkPagin