Skip to Content
Clerk logo

Clerk Docs

Ctrl + K
Go to clerkstage.dev

Verify the active user’s permissions

Clerk provides two kinds of helpers for authorization:

  • protect helpers are opinionated and will block additional processing for unauthorized users, either by not rendering children or by throwing errors. The <Protect> component and the experimental auth().protect() method fall into this category.
  • has helpers are more composable and flexible. They allow you to check and see what permissions a user has. You can decide what to do if the user lacks the permission.

Both kinds of helpers can check a user's role and permissions. The recommended approach is to verify a user's permissions. Roles can be added and removed and their permissions changed. Authorizing by permissions is explicit.

has()

Clerk's has() function can be used on both the frontend and the backend to determine if the user has a role or permission.

has() can be used anywhere that Clerk returns an Authentication object:

  • auth() in Next.js App Router
  • useAuth() in Client Components, including during SSR
  • getAuth(request) in server contexts outside of the App Router and SSR (Remix Loaders, Node, Express, Fastify, etc)

Authorization in Client Components

The examples below work for both SSR and CSR. Examples are written for Next.js App Router but they are supported by any React meta framework, such as Remix or Gatsby.

The following snippet uses Clerk's <Protect> component to only render the form for users with the org:team_settings:manage permission.

/app/dashboard/settings/form.tsx
'use client'; import { Protect } from "@clerk/nextjs"; export function SettingsForm(){ return ( <Protect permission="org:team_settings:manage" fallback={<p>You are not allowed to see this section.</p>} > <form> .... </form> </Protect> ) }

Authorization in React Server Components

The following example uses has() to inspect a user's permissions granularly. If the user doesn't have the org:team_settings:read permission, the component returns null instead of rendering its children.

/app/dashboard/settings/layout.tsx
import type { PropsWithChildren } from "react"; import { auth } from "@clerk/nextjs/server"; export default function SettingsLayout(props: PropsWithChildren){ const { has } = auth() const canAccessSettings = has({permission: "org:team_settings:read"}); if(!canAccessSettings) return null; return props.children }

Authorization in endpoints

import { auth } from "@clerk/nextjs/server"; export default function ServerComponent() { async function myAction() { 'use server' const { has } = auth(); const canManage = has({permission:"org:team_settings:manage"}); ... // Perform a DB operation ... } }

Authorization in Remix Loaders

export const loader: LoaderFunction = async args => { const { has } = await getAuth(args); if(has({permission: "org:team_settings:manage"})){ return redirect('/request-access'); } return {}; }; export default function Settings() { return ( <div> <h1>Settings Page</h1> </div> ); }

Authorization in JS SDK

If you are not using React or any of the meta-frameworks we support, there's a good chance that you are using Clerk.js directly. In that case, the following example can help.

import Clerk from '@clerk/clerk-js' const clerk = new Clerk(...) await clerk.load(...) const canManageSettings = clerk.session.checkAuthorization({ permission: "org:team_settings:manage" })

Authorize with roles

Performing role checks is not considered a best-practice and developers should avoid it as much as possible. Usually, complex role checks can be refactored with a single permission check.

You can pass a role the same way you can pass a permission in all the examples above.

The following example uses <Protect>'s condition prop to conditionally render its children if the user is either an org:admin or an org:billing_manager.

/app/dashboard/settings/layout.tsx
import type { PropsWithChildren } from "react"; import { Protect } from "@clerk/nextjs"; export default function SettingsLayout(props: PropsWithChildren){ return ( <Protect condition={has => has({role: "org:admin"}) || has({role: "org:billing_manager"})} > {props.children} </Protect> ) }

What did you think of this content?

Clerk © 2023