<Protect>
The <Protect>
component protects content or even entire routes by checking if the user has been granted a specific type of access control (role, permission, feature, or plan). You can pass it a fallback
prop that will be rendered if the user does not have the access control.
<Protect>
can be used both client-side and server-side (in Server Components).
- Name
condition?
- Type
has => boolean
- Description
Optional conditional logic that renders the children if it returns
true
.
- Name
fallback?
- Type
JSX
- Description
Optional UI to show when a user doesn't have the correct type of access control to access the protected content.
- Name
feature?
- Type
string
- Description
Optional string corresponding to a feature.
- Name
plan?
- Type
string
- Description
Optional string corresponding to a plan.
- Name
permission?
- Type
string
- Description
Optional string corresponding to a permission in the format
org:<resource>:<action>
- Name
role?
- Type
string
- Description
Optional string corresponding to a role in the format
org:<role>
- Name
treatPendingAsSignedOut?
- Type
boolean
- Description
A boolean that indicates whether to treat pending sessions as signed out. Defaults to
false
.
Usage
To limit who is able to see the content that <Protect>
renders, you can pass one of the access control props: permission
, role
, feature
, or plan
. It's recommended to use permission-based authorization over role-based authorization, and feature-based authorization over plan-based authorization, as they are more flexible, easier to manage, and more secure.
If you do not pass any of the access control props, <Protect>
will render its children if the user is signed in, regardless of their role or its permissions.
For more complex authorization logic, pass conditional logic to the condition
prop.
Render content by permissions
The following example demonstrates how to use the <Protect />
component to protect content by checking if the user has the org:invoices:create
permission.
import { Protect } from '@clerk/nextjs'
export default function Page() {
return (
<Protect
permission="org:invoices:create"
fallback={<p>You do not have the permissions to create an invoice.</p>}
>
<p>Users with permission org:invoices:create can see this.</p>
</Protect>
)
}
import { Protect } from '@clerk/clerk-react'
export default function Page() {
return (
<Protect
permission="org:invoices:create"
fallback={<p>You do not have the permissions to create an invoice.</p>}
>
<p>Users with permission org:invoices:create can see this.</p>
</Protect>
)
}
---
import { Protect } from '@clerk/astro/components'
---
<Protect permission="org:invoices:create">
<p slot="fallback">You do not have the permissions to create an invoice.</p>
<p>Users with permission org:invoices:create can see this.</p>
</Protect>
import { Protect } from '@clerk/clerk-expo'
import { Text } from 'react-native'
export default function Screen() {
return (
<Protect
permission="org:invoices:create"
fallback={<Text>You do not have the permissions to create an invoice.</Text>}
>
<Text>Users with permission org:invoices:create can see this.</Text>
</Protect>
)
}
import { Protect } from '@clerk/react-router'
export default function InvoicesPage() {
return (
<Protect
permission="org:invoices:create"
fallback={<p>You do not have the permissions to create an invoice.</p>}
>
<p>Users with permission org:invoices:create can see this.</p>
</Protect>
)
}
import { Protect } from '@clerk/tanstack-react-start'
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/invoices')({
component: InvoicesPage,
})
function InvoicesPage() {
return (
<Protect
permission="org:invoices:create"
fallback={<p>You do not have the permissions to create an invoice.</p>}
>
<p>Users with permission org:invoices:create can see this.</p>
</Protect>
)
}
<script setup lang="ts">
import { Protect } from '@clerk/vue'
</script>
<template>
<Protect permission="org:invoices:create">
<template #fallback>
<p>You do not have the permissions to create an invoice.</p>
</template>
<p>Users with permission org:invoices:create can see this.</p>
</Protect>
</template>
Render content by role
While authorization by permission
is recommended, for convenience, <Protect>
allows a role
prop to be passed.
The following example demonstrates how to use the <Protect />
component to protect content by checking if the user has the org:billing
role.
import { Protect } from '@clerk/nextjs'
export default function ProtectPage() {
return (
<Protect
role="org:billing"
fallback={<p>Only a member of the Billing department can access this content.</p>}
>
<p>Users with role org:billing can see this.</p>
</Protect>
)
}
import { Protect } from '@clerk/clerk-react'
export default function Page() {
return (
<Protect
role="org:billing"
fallback={<p>Only a member of the Billing department can access this content.</p>}
>
<p>Users with role org:billing can see this.</p>
</Protect>
)
}
---
import { Protect } from '@clerk/astro/components'
---
<Protect role="org:billing">
<p slot="fallback">Only a member of the Billing department can access this content.</p>
<p>Users with role org:billing can see this.</p>
</Protect>
import { Protect } from '@clerk/clerk-expo'
import { Text } from 'react-native'
export default function Screen() {
return (
<Protect
permission="org:billing"
fallback={<Text>Only a member of the Billing department can access this content.</Text>}
>
<Text>Users with role org:billing can see this.</Text>
</Protect>
)
}
import { Protect } from '@clerk/react-router'
export default function BillingPage() {
return (
<Protect
role="org:billing"
fallback={<p>Only a member of the Billing department can access this content.</p>}
>
<p>Users with role org:billing can see this.</p>
</Protect>
)
}
import { Protect } from '@clerk/tanstack-react-start'
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/billing')({
component: BillingPage,
})
function BillingPage() {
return (
<Protect
role="org:billing"
fallback={<p>Only a member of the Billing department can access this content.</p>}
>
<p>Users with role org:billing can see this.</p>
</Protect>
)
}
<script setup lang="ts">
import { Protect } from '@clerk/vue'
</script>
<template>
<Protect role="org:billing">
<template #fallback>
<p>Only a member of the Billing department can access this content.</p>
</template>
<p>Users with role org:billing can see this.</p>
</Protect>
</template>
Render content by plan
The following example demonstrates how to use <Protect />
to protect content by checking if the user has a plan.
import { Protect } from '@clerk/nextjs'
export default function ProtectPage() {
return (
<Protect
plan="bronze"
fallback={<p>Sorry, only subscribers to the Bronze plan can access this content.</p>}
>
<p>Welcome, Bronze subscriber!</p>
</Protect>
)
}
import { Protect } from '@clerk/clerk-react'
export default function Page() {
return (
<Protect
plan="bronze"
fallback={<p>Sorry, only subscribers to the Bronze plan can access this content.</p>}
>
<p>Welcome, Bronze subscriber!</p>
</Protect>
)
}
---
import { Protect } from '@clerk/astro/components'
---
<Protect plan="bronze">
<p slot="fallback">Sorry, only subscribers to the Bronze plan can access this content.</p>
<p>Welcome, Bronze subscriber!</p>
</Protect>
import { Protect } from '@clerk/clerk-expo'
import { Text } from 'react-native'
export default function Page() {
return (
<Protect
plan="bronze"
fallback={<Text>Sorry, only subscribers to the Bronze plan can access this content.</Text>}
>
<Text>Welcome, Bronze subscriber!</Text>
</Protect>
)
}
import { Protect } from '@clerk/react-router'
export default function BronzePage() {
return (
<Protect
plan="bronze"
fallback={<p>Sorry, only subscribers to the Bronze plan can access this content.</p>}
>
<p>Welcome, Bronze subscriber!</p>
</Protect>
)
}
import { Protect } from '@clerk/tanstack-react-start'
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/bronze')({
component: BronzePage,
})
function BronzePage() {
return (
<Protect
plan="bronze"
fallback={<p>Sorry, only subscribers to the Bronze plan can access this content.</p>}
>
<p>Welcome, Bronze subscriber!</p>
</Protect>
)
}
Render content by feature
The following example demonstrates how to use <Protect />
to protect content by checking if the user has a feature.
import { Protect } from '@clerk/nextjs'
export default function Page() {
return (
<Protect
feature="premium_access"
fallback={
<p>Sorry, only subscribers with the Premium Access feature can access this content.</p>
}
>
<p>Congratulations! You have access to the Premium Access feature.</p>
</Protect>
)
}
import { Protect } from '@clerk/clerk-react'
export default function Page() {
return (
<Protect
feature="premium_access"
fallback={
<p>Sorry, only subscribers with the Premium Access feature can access this content.</p>
}
>
<p>Congratulations! You have access to the Premium Access feature.</p>
</Protect>
)
}
---
import { Protect } from '@clerk/astro/components'
---
<Protect feature="premium_access">
<p slot="fallback">
Sorry, only subscribers with the Premium Access feature can access this content.
</p>
<p>Congratulations! You have access to the Premium Access feature.</p>
</Protect>
import { Protect } from '@clerk/clerk-expo'
import { Text } from 'react-native'
export default function Page() {
return (
<Protect
feature="premium_access"
fallback={
<Text>
Sorry, only subscribers with the Premium Access feature can access this content.
</Text>
}
>
<Text>Congratulations! You have access to the Premium Access feature.</Text>
</Protect>
)
}
import { Protect } from '@clerk/react-router'
export default function PremiumAccessPage() {
return (
<Protect
plan="premium_access"
fallback={
<p>Sorry, only subscribers with the Premium Access feature can access this content.</p>
}
>
<p>Congratulations! You have access to the Premium Access feature.</p>
</Protect>
)
}
import { Protect } from '@clerk/tanstack-react-start'
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/premium-access')({
component: PremiumAccessPage,
})
function PremiumAccessPage() {
return (
<Protect
plan="premium_access"
fallback={
<p>Sorry, only subscribers with the Premium Access feature can access this content.</p>
}
>
<p>Congratulations! You have access to the Premium Access feature.</p>
</Protect>
)
}
Render content conditionally
The following example uses <Protect>
's condition
prop to conditionally render its children if the user has the correct role.
import type { PropsWithChildren } from 'react'
import { Protect } from '@clerk/nextjs'
export default function Page() {
return (
<Protect
condition={(has) => has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' })}
fallback={<p>Only an Admin or Billing Manager can access this content.</p>}
>
<p>The settings page.</p>
</Protect>
)
}
import { Protect } from '@clerk/clerk-react'
export default function Page() {
return (
<Protect
condition={(has) => has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' })}
fallback={<p>Only an Admin or Billing Manager can access this content.</p>}
>
<p>The settings page.</p>
</Protect>
)
}
---
import { Protect } from '@clerk/astro/components'
---
<Protect condition={(has) => has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' })}>
<p slot="fallback">Only an Admin or Billing Manager can access this content.</p>
<p>The settings page.</p>
</Protect>
import { Protect } from '@clerk/clerk-expo'
import { Text } from 'react-native'
export default function Page() {
return (
<Protect
condition={(has) => has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' })}
fallback={<Text>Only an Admin or Billing Manager can access this content.</Text>}
>
<Text>The settings page.</Text>
</Protect>
)
}
import { Protect } from '@clerk/react-router'
export default function SettingsPage() {
return (
<Protect
condition={(has) => has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' })}
fallback={<p>Only an Admin or Billing Manager can access this content.</p>}
>
<p>The settings page.</p>
</Protect>
)
}
import { Protect } from '@clerk/tanstack-react-start'
import { createFileRoute } from '@tanstack/react-router'
export const Route = createFileRoute('/settings')({
component: SettingsPage,
})
function SettingsPage() {
return (
<Protect
condition={(has) => has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' })}
fallback={<p>Only an Admin or Billing Manager can access this content.</p>}
>
<p>The settings page.</p>
</Protect>
)
}
<script setup>
import { Protect } from '@clerk/vue'
</script>
<template>
<Protect :condition="(has) => has({ role: 'org:admin' }) || has({ role: 'org:billing_manager' })">
<template #fallback>
<p>Only an Admin or Billing Manager can access this content.</p>
</template>
<p>The settings page.</p>
</Protect>
</template>
Feedback
Last updated on