Clerk logo

Clerk Docs

Ctrl + K
Go to clerkstage.dev
Check out a preview of our new docs.

Organization Switching

Learn how to switch the active organization and how it impacts the JWT

Overview

Within the Clerk organization feature, there is a concept of an active organization. The active organization is the current organization that will be returned by the useOrganization() hook or by Clerk.organization.

const useOrganizationParams = {
invitationList: { limit, offset }, // Pagination params
membershipList: { limit, offset } // Pagination params
};
const {
isLoaded,
organization,
invitationList,
membershipList,
membership,
} = useOrganization(useOrganizationParams);

The organization attributes are updated automatically and will re-render their respective components whenever you set a different active organization using the setActive({ organization }) method or update any of the memberships or invitations. There is no need to manage the organization updating manually.

Active organization in JWT

Clerk stores the active organization identifier in the session token under the org_id property. The org_role property will also reflect the user's current role within the active organization. By storing these claims in the JWT, these values can be accessed without making a network call.

Determine the active organization from the backend

Having enabled the Organizations feature, session tokens generated by Clerk contain the additional claims org_id, org_role and orgs which can be used on the server or edge side of your application.

These claims area accessible through the req.auth.claims path, where all the Clerk token claims reside.

/** Next.js API route. */
import { requireAuth } from "@clerk/nextjs/api";
/* Return the user's active organization id and role. */
export default requireAuth((req, res) => {
const { org_id, org_role } = req.auth.claims;
res.json({
orgId: org_id,
role: org_role,
});
});

In the same manner you can protect organization pages for administrators securely on the server-side and also fetch any kind of data needed for server-side rendering.

import { withServerSideAuth } from "@clerk/nextjs/ssr";
import { organizations } from "@clerk/nextjs/api";
const OrganizationAdmin = ({
organizationName,
}: {
organizationName: string;
}) => {
return <p>Admin page for: {organizationName}</p>;
};
export const getServerSideProps = withServerSideAuth(
async ({ req, resolvedUrl, query }) => {
const { sessionId, claims } = req.auth;
/** If the user is not signed in, redirect him to the sign in page. */
if (!sessionId) {
return {
redirect: { destination: "/sign-in?redirect_url=" + resolvedUrl },
props: {},
};
}
const isCurrentOrganizationAdmin =
claims.org_id === query.orgId && claims.org_role === "admin";
/** If the user's current organization role is not an admin, redirect them home. */
if (!isCurrentOrganizationAdmin) {
return {
redirect: { destination: "/" },
props: {},
};
}
/** Query the Node.js backend API to retrieve any organization information for the SSR step. */
const organization = await organizations.getOrganization({
organizationId: claims.org_id as string,
});
return {
props: { organizationName: organization.name },
};
}
);
export default OrganizationAdmin;

Usage

Example implementation in Next.js of an organization switcher:

1
import { useOrganization, useOrganizationList } from '@clerk/nextjs';
2
import Select from 'react-select';
3
4
function createOrganizationOptions(organizationList) {
5
return organizationList.map(({ organization }) => ({
6
value: organization.id,
7
label: organization.name
8
}));
9
}
10
11
export default function Switcher() {
12
const { setActive, organizationList, isLoaded } = useOrganizationList();
13
const { organization } = useOrganization();
14
15
if (!isLoaded) {
16
return null;
17
}
18
19
const handleOrgChange = e => {
20
setActive({ organization: e.value });
21
};
22
23
if (!organization) {
24
return null;
25
}
26
27
return (
28
<Select
29
options={createOrganizationOptions(organizationList)}
30
onChange={handleOrgChange}
31
value={{ value: organization.id, label: organization.name }}
32
/>
33
);
34
}
35

Was this helpful?

Clerk © 2023